<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"vchao.top","root":"/","scheme":"Muse","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="怀揣好奇，梦想改变世界的菜鸟极客">
<meta property="og:type" content="website">
<meta property="og:title" content="乘风破浪">
<meta property="og:url" content="http://vchao.top/page/3/index.html">
<meta property="og:site_name" content="乘风破浪">
<meta property="og:description" content="怀揣好奇，梦想改变世界的菜鸟极客">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="vchao">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="http://vchao.top/page/3/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>乘风破浪</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">乘风破浪</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://vchao.top/2021/08/25/%E3%80%90Vue%E3%80%91%E9%A1%B9%E7%9B%AE%E9%83%A8%E7%BD%B2/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="vchao">
      <meta itemprop="description" content="怀揣好奇，梦想改变世界的菜鸟极客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="乘风破浪">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/08/25/%E3%80%90Vue%E3%80%91%E9%A1%B9%E7%9B%AE%E9%83%A8%E7%BD%B2/" class="post-title-link" itemprop="url">【Vue】项目部署</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-08-25 22:42:51 / 修改时间：22:37:20" itemprop="dateCreated datePublished" datetime="2021-08-25T22:42:51+08:00">2021-08-25</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Vue/" itemprop="url" rel="index"><span itemprop="name">Vue</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="一-vue项目打包"><a href="#一-vue项目打包" class="headerlink" title="一. vue项目打包"></a>一. vue项目打包</h2><p>修改config/index.js的assetsPublicPath为 ./（注意一定是build里面的，下面dev中也有这个配置）</p>
<p>这个路径的配置很重要，默认是项目名称。如果没有修改路径会变成这样，访问不到打包后的文件。就算返回200，你会发现返回的根本不是那些打包后的文件。</p>
<p>打包成dist文件</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build</span><br></pre></td></tr></table></figure>

<p>这时我们就可以把生成的dist文件扔到服务器就可以了。</p>
<h2 id="二-配置nginx"><a href="#二-配置nginx" class="headerlink" title="二. 配置nginx"></a>二. 配置nginx</h2><p>安装nginx<br>安装的步骤不再赘述，安装后通过<code>nginx -v</code> 可测试是否安装成功</p>
<p>修改nginx的配置文件<br>默认路径：</p>
<p>vim /etc/nginx/nginx.conf </p>
<p>在 http{ } 中配置一个server</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">server &#123;</span><br><span class="line">    listen 8080;     #1.你想让你的这个项目跑在哪个端口</span><br><span class="line">    server_name 47.94.76.91;     #2.当前服务器ip</span><br><span class="line">    location / &#123;</span><br><span class="line">        root   /home/dist/;     #3.dist文件的位置(我是直接放在home目录下了) </span><br><span class="line">        try_files $uri $uri/ /index.html;     #4.重定向,内部文件的指向(照写)</span><br><span class="line">    &#125;</span><br><span class="line">    location /api &#123;  #4.当请求跨域时配置端口转发</span><br><span class="line">        proxy_pass http://47.92.76.97:8848/api; #5.转发地址</span><br><span class="line">    &#125; </span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<blockquote>
<p>我的示例如下：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">location /apis &#123;</span><br><span class="line">    rewrite  ^.+apis/?(.*)$ /$1 break;</span><br><span class="line">    include  uwsgi_params;</span><br><span class="line">    proxy_pass   http://jiuhe.vchao.top; #此处修改为自己的请求地址</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


</blockquote>
<p>跨域问题在这里着重说一下：</p>
<p>这里的跨域配置是打包后，nginx做的代理转发。在开发模式的proxytable没有任何关系。<br>如果nginx不进行跨域的配置，虽然项目部署了，但是服务根本就会访问不到</p>
<h2 id="三-开放端口"><a href="#三-开放端口" class="headerlink" title="三.开放端口"></a>三.开放端口</h2><p>像阿里云的服务器都需要开通端口才可以访问的。这个不做详细介绍。<br>然后我们重启nginx就可以访问我们部署的项目了 service nginx restart</p>
<p>————————————————<br>版权声明：本文为CSDN博主「优雅的王德奥」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。<br>原文链接：<a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_42565137/article/details/90577950">https://blog.csdn.net/weixin_42565137/article/details/90577950</a></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://vchao.top/2021/08/25/SVG%20-%20%E5%9C%A8Android%E4%B8%AD%E4%BD%BF%E7%94%A8%E7%9F%A2%E9%87%8F%E5%9B%BE%E5%85%A8%E6%94%BB%E7%95%A5/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="vchao">
      <meta itemprop="description" content="怀揣好奇，梦想改变世界的菜鸟极客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="乘风破浪">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/08/25/SVG%20-%20%E5%9C%A8Android%E4%B8%AD%E4%BD%BF%E7%94%A8%E7%9F%A2%E9%87%8F%E5%9B%BE%E5%85%A8%E6%94%BB%E7%95%A5/" class="post-title-link" itemprop="url">SVG - 在Android中使用矢量图全攻略</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-08-25 22:42:51 / 修改时间：22:37:20" itemprop="dateCreated datePublished" datetime="2021-08-25T22:42:51+08:00">2021-08-25</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h1><h2 id="什么是矢量图，SVG"><a href="#什么是矢量图，SVG" class="headerlink" title="什么是矢量图，SVG"></a>什么是矢量图，SVG</h2><blockquote>
<p>SVG全称：可伸缩矢量图形 (Scalable Vector Graphics)<br>SVG 用来定义用于网络的基于矢量的图形<br>SVG 使用 XML 格式定义图形<br>SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失<br>SVG 是万维网联盟（W3C）的标准，与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体</p>
</blockquote>
<p>与位图（Bitmap）相对，SVG不会像位图一样因为缩放而让图片质量下降。</p>
<h2 id="优缺点"><a href="#优缺点" class="headerlink" title="优缺点"></a>优缺点</h2><p><strong>优点：</strong><br>1.矢量图使用点和线来描述图形，所有文件会比较小，同时也能提供高清晰的画面。<br>2.矢量图缩放自由且不会失真，完全适配于任何分辨率的屏幕。<br>3.矢量图是以xml语言来描述的，所以它修改自如，节约空间，使用方便。<br>4.矢量图色彩分辨率非常高清，同时支持滤镜。<br>5.跨平台，因为矢量图是纯文本格式来描述的，所以不受平台的限制。</p>
<p><strong>缺点：</strong><br>SVG 是在要用图的时候再把图画出来，所以在图片显示的时候会花费更多的时间消耗更多的资源；此外，SVG 并不太适合层次过于复杂细节过于繁多的图片。</p>
<p>简单来说，SVG就是描述图形的xml文件，缩放不变形。<br>和安卓中的shape有点异曲同工之妙。</p>
<h2 id="获取SVG图片"><a href="#获取SVG图片" class="headerlink" title="获取SVG图片"></a>获取SVG图片</h2><h3 id="获取途径"><a href="#获取途径" class="headerlink" title="获取途径"></a>获取途径</h3><p>SVG的获取途径有以下几种：</p>
<ol>
<li>Android自身提供</li>
<li>美工切图</li>
<li>自己从网站下载</li>
</ol>
<p>android提供的矢量图多数不能满足我们的需求，美工切图的情况此处略去不表，来讲讲从网站下载的方法。 </p>
<h3 id="【iconfont】阿里妈妈矢量图标平台"><a href="#【iconfont】阿里妈妈矢量图标平台" class="headerlink" title="【iconfont】阿里妈妈矢量图标平台"></a>【iconfont】阿里妈妈矢量图标平台</h3><p>在Android上如何使用，官网已经做了非常详细的介绍。<br>建议先戳 —&gt;   <a target="_blank" rel="noopener" href="http://www.iconfont.cn/help/detail?helptype=code">http://www.iconfont.cn/help/detail?helptype=code</a></p>
<p><strong>使用流程</strong><br>使用起来也很简单,总结就是：</p>
<ul>
<li>首先新建一个自己的项目;</li>
<li>从iconfont平台选择要使用到的图标或者本地导入svg图片到项目中；</li>
<li>下载代码,把iconfont.svg和iconfont.ttf文件导入到项目中的assets文件夹中；</li>
<li>用TextView代替ImagerView，找到图标相对应的 HTML 实体字符码给textView设置；</li>
<li>textview设置大小跟颜色，图标的大小颜色也会改变（这里大小最好用dp为单位，这样不会随着手机字体大小的改变而改变图标的大小）；</li>
<li>为Textview设置指定的ttf文字；<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">TextView</span></span></span><br><span class="line"><span class="tag">   <span class="attr">android:layout_width</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">   <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">   <span class="attr">android:text</span>=<span class="string">&quot;<span class="symbol">&amp;#xe6dd;</span>&quot;</span></span></span><br><span class="line"><span class="tag">   <span class="attr">android:textSize</span>=<span class="string">&quot;50dp&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>
//为TextView设置指定ttf文字<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Typeface iconfont = Typeface.createFromAsset(getAssets(), <span class="string">&quot;iconfont/iconfont.ttf&quot;</span>);</span><br><span class="line">TextView textview = (TextView)findViewById(R.id.text_icon);</span><br><span class="line">textview.setTypeface(iconfont);</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="iconfont的封装"><a href="#iconfont的封装" class="headerlink" title="iconfont的封装"></a>iconfont的封装</h3><p>每次都给TextView设置指定文字也很繁琐，而且不断读取iconfont.ttf文字,也会浪费内存。我们可以做个优化，把这个抽离出来。<br>首先我们要读取到的是assets目录下的iconfont.ttf文件；这里我把它放到自定义的Application中，这样就只要读取一次，代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyApplication</span> <span class="keyword">extends</span> <span class="title">Application</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> Typeface iconfont;</span><br><span class="line"></span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Typeface <span class="title">getIconfont</span><span class="params">(Context context)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (iconfont != <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> iconfont;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        iconfont = Typeface.createFromAsset(context.getAssets(), <span class="string">&quot;iconfont/iconfont.ttf&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> iconfont;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里就实例化了iconfont。然后给每TextView设置Typeface，这肯定不是我们想要的，所以我们可以通过自定义控件的方式，在初始化时执行setTypeface。代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TextViewIcon</span> <span class="keyword">extends</span> <span class="title">AppCompatTextView</span> </span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">TextViewIcon</span><span class="params">(Context context)</span> </span>&#123;</span><br><span class="line">	    <span class="keyword">super</span>(context);</span><br><span class="line">	    init(context);</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">TextViewIcon</span><span class="params">(Context context, AttributeSet attrs)</span> </span>&#123;</span><br><span class="line">	    <span class="keyword">super</span>(context, attrs);</span><br><span class="line">	    init(context);</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">TextViewIcon</span><span class="params">(Context context, AttributeSet attrs, <span class="keyword">int</span> defStyleAttr)</span> </span>&#123;</span><br><span class="line">	    <span class="keyword">super</span>(context, attrs, defStyleAttr);</span><br><span class="line">	    init(context);</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">(Context context)</span> </span>&#123;</span><br><span class="line">	    setTypeface(VcApplication.getIconfont(context));</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如此即可在layout文件中直接使用了</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">com.xxxxx.xxxxx.TextViewIcon</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:id</span>=<span class="string">&quot;@+id/text_icon&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:text</span>=<span class="string">&quot;<span class="symbol">&amp;#xe643;</span>&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:textColor</span>=<span class="string">&quot;#ff0000&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:textSize</span>=<span class="string">&quot;50sp&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="iconfont动态设置"><a href="#iconfont动态设置" class="headerlink" title="iconfont动态设置"></a>iconfont动态设置</h2><p>动态设置通俗的说就是在java代码里动态的调整图标的大小颜色或改变图片，iconfont改变大小颜色这很简单直接调用TextView的setTextSize和setTextColor就可以了，动态设置图片是不是setText呢？</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">textview.setText(<span class="string">&quot;&amp;#xe643;&quot;</span>);</span><br></pre></td></tr></table></figure>
<p>运行发现并不如我们所愿，这里涉及到unicode 字符的问题,<br>把代码稍改一下,用 unicode 字符来表示,”&amp;#x” 替换成 “\u”，改成下面这样，问题就可以解决</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">textview.settext(<span class="string">&quot;\ue643&quot;</span>);<span class="comment">// &quot;&amp;#x&quot; 替换成 &quot;\u&quot;，用 unicode 字符来表示</span></span><br></pre></td></tr></table></figure>


<h1 id="使用SVG"><a href="#使用SVG" class="headerlink" title="使用SVG"></a>使用SVG</h1><p>首先需要明确的是：Android不支持直接在项目中使用svg的图片。<br>但是Google在Android5.X中提供了两个新API来支持SVG： </p>
<ul>
<li>VectorDrawable </li>
<li>AnimatedVectorDrawable</li>
</ul>
<p>所以在Android中使用SVG的话，要区分5.0以上以及5.0以下的不同情况。</p>
<p>在Android Studio 使用SVG矢量图<br>在drawable文件夹上右键-&gt;new-&gt;Vector Asset </p>
<p>选择自带的图标或者从本地选取</p>
<p>android:viewportWidth与android:viewportHeight:是指当前Drawable对应的虚拟Canvas的大小, 之所以说是虚拟的是因为实际上并不存在这样一个Canvas, 又之所以需要这个值是因为在+ + 标签中的路径数据要基于具体的坐标系来绘制.</p>
<p><code>&lt;vector&gt;</code> 是 VectorDrawable 对应的根标签<br>android:width与android:height:对应矢量图的实际大小</p>
<blockquote>
<p>矢量图是可以无限大且不失真的, 但通常一个图片都会有一个原始大小,将在其父控件大小都设置为wrap_content时起作用)<br> 基于加载性能考虑，Google推荐限定在 200x200dp 以内。</p>
</blockquote>
<p>android:viewportWidth与android:viewportHeight是指当前Drawable对应的Canvas的大小，<br>一般与上面的android:width与android:height:成比例定义。</p>
<blockquote>
<p>用于为<code>&lt;path/&gt;</code>标签中的路径数据提供绘制位置的参考坐标系及绘制范围<br><code>&lt;path/&gt;</code>标签对应路径信息, 这里的path与我们自定义绘制图形时用的Path原理一样, 就是记录一些绘图操作, 具体对应其中的 pathData。</p>
</blockquote>
<p>android:fillColor为默认黑色（#FF000000）时，在View容器内将使用tint颜色取代，否则将呈现为android:fillColor与tint的混合颜色。</p>
<p><code>&lt;path/&gt;</code>标签:对应路径信息, 这里的path与我们自定义绘制图形时用的Path原理一样, 就是记录一些绘图操作, 具体对应其中的pathData.PathData中对应的路径描述符号不需要我们去记, 通常情况下由绘图软件生成svg图片再从svg文件中提取.<br><code>&lt;path/&gt;</code>路径的路径描述指令含义表：</p>
<p>M = moveto 相当于 android Path 里的moveTo(),用于移动起始点<br>L = lineto 相当于 android Path 里的lineTo()，用于画线<br>H = horizontal lineto 用于画水平线<br>V = vertical lineto 用于画竖直线<br>C = curveto 相当于cubicTo(),三次贝塞尔曲线<br>S = smooth curveto 同样三次贝塞尔曲线，更平滑<br>Q = quadratic Belzier curve quadTo()，二次贝塞尔曲线<br>T = smooth quadratic Belzier curveto 同样二次贝塞尔曲线，更平滑<br>A = elliptical Arc 相当于arcTo()，用于画弧<br>Z = closepath 相当于closeTo(),关闭path</p>
<p>大写代表绝对位置, 小写代表相对位置<br>官方标准定义细则参考：SVG Paths Definition - W3C</p>
<p>矢量图创建完成后使用方法跟其他格式的图片用法一样。</p>
<p>我们这里提供三种解决方案：</p>
<ul>
<li><p>使用支持库PathView<br><a target="_blank" rel="noopener" href="https://github.com/geftimov/android-pathview">https://github.com/geftimov/android-pathview</a><br>不仅支持直接使用svg，还可以自定义路径，使用是 svg动画。详情请看github介绍</p>
</li>
<li><p>将SVG转换为VectorDrawable<br><a target="_blank" rel="noopener" href="http://inloop.github.io/svg2android/">http://inloop.github.io/svg2android/</a><br>该在线网站可以将svg转换为VectorDrawable</p>
</li>
<li><p>将矢量图制作成字体图标<br>step1:从iconfont平台选取图标下载到本地，复制字体文件到项目的assets目录。<br>step2:打开下载下来的文件，并打开demo.html,找到图标对应的HTML实体字符码。<br>step3:打开res／values／strings.xml，添加string值。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">string</span> <span class="attr">name</span>=<span class="string">&quot;app_name&quot;</span>&gt;</span>My Application<span class="tag">&lt;/<span class="name">string</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">string</span> <span class="attr">name</span>=<span class="string">&quot;icon_cart&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">string</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">string</span> <span class="attr">name</span>=<span class="string">&quot;icon_wl&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">string</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br></pre></td></tr></table></figure></li>
</ul>
<p>step4:为TextView设置string值。</p>
<p>step5:为TextView指定文字。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">     <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">     setContentView(R.layout.activity_main);</span><br><span class="line">     mTv = (TextView) findViewById(R.id.tv_main);</span><br><span class="line">     Typeface iconfont = Typeface.createFromAsset(getAssets(),    <span class="string">&quot;iconfont.ttf&quot;</span>);</span><br><span class="line">     mTv.setTypeface(iconfont);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<p>5.封装使用<br>上面的使用的方式需要对每一个TextView指定字体，并且需要下载图标并获取对应的字符编码，使用起来非常的麻烦，github上提供了一个开源的库封装了操作，简化了使用：<br><a target="_blank" rel="noopener" href="https://github.com/mikepenz/Android-Iconics">https://github.com/mikepenz/Android-Iconics</a></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">TextView</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:text</span>=<span class="string">&quot;&#123;gmd-chart&#125; Chart&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:textColor</span>=<span class="string">&quot;@android:color/black&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;56dp&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:textSize</span>=<span class="string">&quot;16sp&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p>6.SVG动画</p>
<p>6.1 使用AnimatedVectorDrawable来实现动画<br>SVG学习–AnimatedVectorDrawable的使用</p>
<p>6.2 使用三方库-PathView</p>
<h1 id="可能遇见的坑"><a href="#可能遇见的坑" class="headerlink" title="可能遇见的坑"></a>可能遇见的坑</h1><h2 id="VectorDrawable"><a href="#VectorDrawable" class="headerlink" title="VectorDrawable"></a>VectorDrawable</h2><p>要想在Android使用svg，首先要介绍的肯定是VectorDrawable，VectorDrawable是Android 5.0系统中引入了 VectorDrawable 来支持矢量图(SVG)，同时还引入了 AnimatedVectorDrawable 来支持矢量图动画。<br>官方文档：<br>VectorDrawable,AnimatedVectorDrawable<br>VectorDrawable转换Bitmap</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">Bitmap bitmap;</span><br><span class="line">   <span class="keyword">if</span> (Build.VERSION.SDK_INT&gt;Build.VERSION_CODES.LOLLIPOP)&#123;</span><br><span class="line">       Drawable vectorDrawable = context.getDrawable(R.id.img_vector);</span><br><span class="line">       bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);</span><br><span class="line">       Canvas canvas = <span class="keyword">new</span> Canvas(bitmap);</span><br><span class="line">       vectorDrawable.setBounds(<span class="number">0</span>, <span class="number">0</span>, canvas.getWidth(), canvas.getHeight());</span><br><span class="line">       vectorDrawable.draw(canvas);</span><br><span class="line">   &#125;<span class="keyword">else</span> &#123;</span><br><span class="line">       Drawable drawable = AppCompatDrawableManager.get().getDrawable(context, R.id.img_vector);</span><br><span class="line">       bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);</span><br><span class="line">       Canvas canvas = <span class="keyword">new</span> Canvas(bitmap);</span><br><span class="line">       drawable.setBounds(<span class="number">0</span>, <span class="number">0</span>, canvas.getWidth(), canvas.getHeight());</span><br><span class="line">       drawable.draw(canvas);</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<h2 id="5-0以上版本使用"><a href="#5-0以上版本使用" class="headerlink" title="5.0以上版本使用"></a>5.0以上版本使用</h2><p>Android studio在2.0的版本中可以直接使用svg<br>新建一个SVGDemo项目，</p>
<p>新建Vector Asset文件 </p>
<p>File -&gt; New -&gt; Vector Asset </p>
<p>导入SVG </p>
<p>可以选择Google提供的Material Icon进行导入也可以选择Local File选择本地svg文件进行导入，一般选择后者。对文件命名后点击Next -&gt;Finish在drawable目录下就添加了一个.xml的文件<br>点击可以进行预览，一看是不是很像selector、animation-list只是标签为vector标签 width、height为对应的宽高，可以进行设置，viewportWidth、viewportHeight这个我也不太了解大概就是视图的宽高吧，好像作用不大，没有设置过。path为html中的一个标签用来定义路径，我们只关心path标签中的android:fillColor=”#FBDC00”的属性，用来改变颜色。 </p>
<p>使用SVG</p>
<p>在layout新建一个activity_svg.xml文件</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ImageView</span></span></span><br><span class="line"><span class="tag">   <span class="attr">android:layout_width</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">   <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">   <span class="attr">android:src</span>=<span class="string">&quot;@drawable/ic_china&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p>就是这样简单，也可以当背景使用 </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">LinearLayout</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:background</span>=<span class="string">&quot;@drawable/ic_china&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">LinearLayout</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="5-0以下版本使用SVG"><a href="#5-0以下版本使用SVG" class="headerlink" title="5.0以下版本使用SVG"></a>5.0以下版本使用SVG</h2><p>上面说了在Android5.0以上使用svg图片是没有任何问题，但是怎么兼容5.0以下的机型，很多github第三方开源库可以解决，其实google已经给出了解决方案，我们主要了解原生的解决办法。 </p>
<p>添加兼容性支持<br>首先，你需要在项目的build.gradle脚本中，增加对Vector兼容性的支持，代码如下所示： </p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">android &#123; </span><br><span class="line">	defaultConfig &#123; </span><br><span class="line">		vectorDrawables.useSupportLibrary = <span class="keyword">true</span> </span><br><span class="line">	&#125; </span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure>
<p>在defaultConfig中添加了</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vectorDrawables.useSupportLibrary = <span class="keyword">true</span></span><br></pre></td></tr></table></figure>
<p>当然还需要添加appcompat的支持</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">compile</span> <span class="string">&#x27;com.android.support:appcompat-v7:23.4.0&#x27;</span></span><br></pre></td></tr></table></figure>
<p>在ImageView中使用<br>我们要引用support:appcompat-v7中的view首先我们需要在XML布局文件头部添加：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;</span><br></pre></td></tr></table></figure>

<p>2、 用V7下的AppCompatImageView代替ImageView<br>3、将android:src属性，换成app:srcCompat即可<br>代码如下 :</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">LinearLayout</span> <span class="attr">xmlns:android</span>=<span class="string">&quot;http://schemas.android.com/apk/res/android&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">xmlns:app</span>=<span class="string">&quot;http://schemas.android.com/apk/res-auto&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">android:layout_height</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">android:orientation</span>=<span class="string">&quot;vertical&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">android.support.v7.widget.AppCompatImageView</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">app:srcCompat</span>=<span class="string">&quot;@drawable/ic_china&quot;</span>/&gt;</span></span><br><span class="line"> <span class="tag">&lt;/<span class="name">LinearLayout</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>根据上文是不是能推测出有app:backgroundCompat属性呢，然而并不如我们所愿，没有这样的属性。<br>所以我们只能用 android:background这个属性了，先不管这么多了直接4.4的机器上运行试试，果然崩了，在这里说明下在普通控件上使用Vector，就必须依附于StateListDrawable,InsetDrawable,LayerDrawable,LevelListDrawable,RotateDrawable我们选择selector代码如下：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">selector</span> <span class="attr">xmlns:android</span>=<span class="string">&quot;http://schemas.android.com/apk/res/android&quot;</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">item</span> <span class="attr">android:drawable</span>=<span class="string">&quot;@drawable/ic_china&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">selector</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>这样是不是完了呢？在运行试试还是崩了，这里又是一个坑…..<br>还需要在activity中添加如下代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> &#123;</span><br><span class="line">	AppCompatDelegate.setCompatVectorFromResourcesEnabled(<span class="keyword">true</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>完美解决问题。</p>
<h2 id="VectorDrawable-与-SVG"><a href="#VectorDrawable-与-SVG" class="headerlink" title="VectorDrawable 与 SVG"></a>VectorDrawable 与 SVG</h2><p>Android 5.0（Lollipop, API 21）后，新增了<code>&lt;vector&gt;</code>标签，以VectorDrawable的形式支持SVG类型矢量图形（SVG本质为XML标记描述的图形）。</p>
<p>SVG文件（XML）对应的VectorDrawable资源封装格式为：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">vector</span> <span class="attr">xmlns:android</span>=<span class="string">&quot;http://schemas.android.com/apk/res/android&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:height</span>=<span class="string">&quot;64dp&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:width</span>=<span class="string">&quot;64dp&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:viewportHeight</span>=<span class="string">&quot;600&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:viewportWidth</span>=<span class="string">&quot;600&quot;</span> &gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">group</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:name</span>=<span class="string">&quot;rotationGroup&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:pivotX</span>=<span class="string">&quot;300.0&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:pivotY</span>=<span class="string">&quot;300.0&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:rotation</span>=<span class="string">&quot;45.0&quot;</span> &gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">path</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:name</span>=<span class="string">&quot;v&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:fillColor</span>=<span class="string">&quot;#000000&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:pathData</span>=<span class="string">&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">group</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">vector</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>※ 通常由SVG文件转换为VectorDrawable，而非手工录入</p>
<h3 id="SVG编辑软件"><a href="#SVG编辑软件" class="headerlink" title="SVG编辑软件"></a>SVG编辑软件</h3><p>Inkscape<br>跨平台开源矢量图形编辑软件，免费 + 三平台通用，支持直接编辑XML数据<br>类似的软件还有Illustrator、CorelDraw等</p>
<h3 id="SVG-转-VectorDrawable"><a href="#SVG-转-VectorDrawable" class="headerlink" title="SVG 转 VectorDrawable"></a>SVG 转 VectorDrawable</h3><p>使用 Vector Asset Studio 转换，在res目录右键菜单上选择 New &gt; Vector Asset<br>通过开源项目 svg2android 在线转换<br>※ 初始化VectorDrawable将消耗更多CPU资源，Google推荐将矢量图最大尺寸限定在 200x200dp 以内</p>
<p>VectorDrawable 向后兼容</p>
<p>对于Android 5.0之前的设备，有两种方式兼容VectorDrawable资源：</p>
<ol>
<li>利用 Vector Asset Studio 工具动态生成位图<br>Android Studio 内置一个名为 Vector Asset Studio 的工具，在低版本SDK上编译APK期间，针对VectorDrawable脚本自动生成一组PNG位图资源BitmapDrawable，取代矢量图形（在5.0及以后的手机上运行时会正常引用VectorDrawable）。</li>
</ol>
<p>需要配置build.gradle：</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">defaultConfig &#123;</span><br><span class="line">    vectorDrawables.generatedDensities = [<span class="string">&#x27;hdpi&#x27;</span>,<span class="string">&#x27;xxhdpi&#x27;</span>]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>※ 自动生成PNG时，所支持的VectorDrawable元素子集</p>
<ol start="2">
<li>添加 Support Library 23.2+ 兼容包<br>Support Library 23.2+ 包中包含VectorDrawableCompat和AnimatedVectorDrawableCompat兼容类，用于代码中桥接为BitmapDrawable及其动画支持，其中Drawable最低SDK为Android 2.1，动画最低SDK为Android 3.0</li>
</ol>
<p>※ 兼容包要求使用Gradle 2.0或以上版本，并且不支持VectorDrawable嵌套引用，不支持直接解析为VectorDrawable类型，也不再编译期生成PNG位图</p>
<p>build.gradle配置如下：</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">android &#123;</span><br><span class="line">  defaultConfig &#123;</span><br><span class="line">    vectorDrawables.useSupportLibrary = <span class="keyword">true</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">dependencies</span> &#123;</span><br><span class="line">  <span class="keyword">compile</span> <span class="string">&#x27;com.android.support:appcompat-v7:23.2.0&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>兼容包在矢量资源引用、代码调用时，存在一定限制<br>在 ImageView 等引用 VectorDrawable 资源时，需要使用app:srcCompat取代android:src<br>代码中使用setImageResource()指定资源 id 时，无需更改代码<br>将 VectorDrawable 用于 View 背景时，需要通过以下代码设定：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Resources resources = context.getResources(Resources, <span class="keyword">int</span>, Theme);</span><br><span class="line">Theme theme = context.getTheme();</span><br><span class="line">Drawable drawable = VectorDrawableCompat.create(resources, R.drawable.vector_drawable, theme);</span><br><span class="line">view.setBackground(drawable);</span><br></pre></td></tr></table></figure>
<p>代码中需要进行Drawable的实现类型转换时，可使用以下代码段执行：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.LOLLIPOP) &#123;</span><br><span class="line">   VectorDrawable vectorDrawable =  (VectorDrawable) drawable;</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">   BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="矢量动画"><a href="#矢量动画" class="headerlink" title="矢量动画"></a>矢量动画</h2><p>使用矢量图可进行特殊的动画绘制，比如形态变换、动态绘图等。</p>
<p><strong>主要步骤</strong><br>定义矢量资源及其关联动画 XML 脚本<br>创建矢量图形资源VectorDrawable，并在需要动画特效的子元素上使用属性android:name给定任意动画对象名<br>创建Animator属性动画脚本，可使用ObjectAnimator或AnimatorSet，对VectorDrawable的特定元素属性进行动画控制<br>创建AnimatedVectorDrawable，作用是连接VectorDrawable与Animator，组合为单一动画型Drawable对象<br>创建好的AnimatedVectorDrawable不能直接用于 ImageView，需要通过代码设定，并显式开始执行动画<br><strong>官方文档</strong><br>XML脚本具体定义方式可参考 开发手册 AnimatedVectorDrawable<br>开发手册 内联复合XML资源 提供了通过 AAPT 系统插件，实现单一XML脚本混合定义的方式，需要声明命名空间 <code>xmlns:aapt=&quot;http://schemas.android.com/aapt&quot;</code><br>在线实时输出 XML 脚本<br>Google工程师开发的开源项目 AndroidIconAnimator，可实现在线实时构造、编辑、预览 VectorDrawable 动画，并导出XML脚本，使用教程可参考 Qiita帖子</p>
<p> 代码设置<br>创建好的 VectorDrawable 动画资源，需要通过代码方式加载到 View 容器内，并指定执行动画</p>
<p>使用原生支持的代码设定（5.0 LOLLIPOP, API 21）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ImageView imageView = (ImageView) findViewById(R.id.imageView);</span><br><span class="line">AnimatedVectorDrawable vectorDrawable = (AnimatedVectorDrawable) getResources().getDrawable(AnimatedVectorDrawableRes, Theme);</span><br><span class="line">imageView.setImageDrawable(vectorDrawable);</span><br><span class="line">vectorDrawable.start();</span><br></pre></td></tr></table></figure>
<p>使用 Support Library 时的动画设置<br>矢量动画要求最低SDK为Android 3.0，并且不支持<code>&lt;path&gt;</code>路径类型的变换</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ImageView imageView = (ImageView) findViewById(R.id.imageView);</span><br><span class="line">AnimatedVectorDrawableCompat drawableCompat = AnimatedVectorDrawableCompat.create(context, AnimatedVectorDrawableRes);</span><br><span class="line">imageView.setImageDrawable(drawableCompat);</span><br><span class="line">drawableCompat.start();</span><br></pre></td></tr></table></figure>
<p>可执行的特有动画效果，可参考 VectorDrawable 元素属性列表<br>所有属性中文解释可参考 Android矢量图形与矢量动画<br>其中一种动效实例，可参考博文 Android使用SVG矢量动画<br>特别介绍几个特殊属性：<br><code>&lt;group&gt;</code>元素：<br>rotation：旋转角度，取值为360角度，valueType=floatType<br>pivotX / pivotY：旋转中心坐标，以viewport为参照基准<br><code>&lt;path&gt;</code>元素：<br>pathData：矢量图形的绘制路径数据位点，可动画形变为另一种图案，要求动画参数值必须拥有相同长度参数及一致的路径描述指令，并且 ObjectAnimator 中<code>android:valueType=&quot;pathType&quot;</code>（Support 包不支持该数据进行变换动画）<br>trimPathStart：从路径起始点开始向后裁剪（擦除）的相对距离，取值 [0, 1]，，0 表示路径起始点，1 表示路径结束点，可实现逐步消退、绘制动效，<code>android:valueType=&quot;floatType&quot;</code><br>trimPathEnd：从路径结束点开始向前裁剪的相对距离，取值 [0, 1]，0 表示路径起始点，1 表示路径结束点<br>trimPathOffset：从路径起始、结束点开始裁剪的相对距离，取值 [0, 1]，0 表示不裁剪，1 表示该路径完全不绘制<br><code>&lt;clip-path&gt;</code>元素：遮罩路径、反蒙版路径，该路径范围内的元素才会真正进行绘制，作用于当前所在的<code>&lt;group&gt;</code>内定义在其后面的所有<code>&lt;path&gt;</code>元素<br>pathData：定义遮罩路径，动画操作方式与<code>&lt;path&gt;</code>相同<br>pathData 形变动画参考<br>理解Android VectorDrawable中的pathData命令<br>PathMorphing with AnimatedVectorDrawables in Android<br>【VectAlign】pathData自动算法变换对齐工具</p>
<p>已知bug：<br><code>&lt;animated-vector&gt;</code>标签在使用时会发生错误警告requires API level 21，不影响兼容包的编译运行<br>放置于animator目录内的Animator脚本，需要在<code>&lt;animated-vector&gt;</code>的<code>&lt;target&gt;</code>中手工引用@animator/资源id（自动提示补全菜单失效）<br>使用动画时，ImageView 不能使用android:tint属性，否则会导致Mutate() is not supported for older platform异常崩溃<br>通过 AAPT 标签使用单一脚本混合定义时，Android Studio 会出现识别错误提示<br>矢量动画通过关联 Property Animation 打包为 Drawable 方式实现，对属性的动态修改将影响所有同一 Drawable 资源产生的对象（Drawable 状态共享机制），并且兼容包不支持 mutate() 调用（状态分离，兼容包内要求API 23以上），实际上代码暂时无法访问矢量元素内部属性（如 pathData 等）</p>
<p>文章参考：<br>作者：慕涵盛华    原文：<a target="_blank" rel="noopener" href="https://blog.csdn.net/guofudong2/article/details/81299137">https://blog.csdn.net/guofudong2/article/details/81299137</a><br>作者：Dick_zeng   原文：<a target="_blank" rel="noopener" href="https://blog.csdn.net/dick_zeng/article/details/72473591">https://blog.csdn.net/dick_zeng/article/details/72473591</a><br>作者：陈立扬   原文：<a target="_blank" rel="noopener" href="https://www.cnblogs.com/chenliyang/p/6542896.html">https://www.cnblogs.com/chenliyang/p/6542896.html</a><br>作者：woxingxiao   原文：<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/0555b8c1d26a">https://www.jianshu.com/p/0555b8c1d26a</a><br>作者：慕涵盛华   原文：<a target="_blank" rel="noopener" href="https://blog.csdn.net/guofudong2/article/details/81299137">https://blog.csdn.net/guofudong2/article/details/81299137</a><br><a target="_blank" rel="noopener" href="http://www.w3school.com.cn/svg/index.asp">http://www.w3school.com.cn/svg/index.asp</a></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://vchao.top/2021/08/25/OKhttp%E8%AE%BE%E7%BD%AEUserAgent%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B%E5%84%BF/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="vchao">
      <meta itemprop="description" content="怀揣好奇，梦想改变世界的菜鸟极客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="乘风破浪">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/08/25/OKhttp%E8%AE%BE%E7%BD%AEUserAgent%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B%E5%84%BF/" class="post-title-link" itemprop="url">OKhttp设置UserAgent的那些事儿</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-08-25 22:42:51 / 修改时间：22:37:20" itemprop="dateCreated datePublished" datetime="2021-08-25T22:42:51+08:00">2021-08-25</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <blockquote>
<p>首先科普一下，UserAgent中文名为用户代理，简称 UA，它是一个*特殊字符串头，使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。</p>
</blockquote>
<blockquote>
<p>Okhttp走的并不是原生的http请求，因此它在header里面并没有真正的User-Agent，而是“okhttp/版本号”这样的字符串，因为后台需要统计信息，要求传入自定义的User-Agent。</p>
</blockquote>
<p>首先先看一下怎样正确获取User-Agent。</p>
<p>0x00-正确获取User-Agent</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">private static String getUserAgent() &#123;</span><br><span class="line">        String userAgent = &quot;&quot;;</span><br><span class="line">        if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.JELLY_BEAN_MR1) &#123;</span><br><span class="line">            try &#123;</span><br><span class="line">                userAgent = WebSettings.getDefaultUserAgent(context);</span><br><span class="line">            &#125; catch (Exception e) &#123;</span><br><span class="line">                userAgent = System.getProperty(&quot;http.agent&quot;);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            userAgent = System.getProperty(&quot;http.agent&quot;);</span><br><span class="line">        &#125;</span><br><span class="line">        StringBuffer sb = new StringBuffer();</span><br><span class="line">        for (int i = 0, length = userAgent.length(); i &lt; length; i++) &#123;</span><br><span class="line">            char c = userAgent.charAt(i);</span><br><span class="line">            if (c &lt;= &#x27;\u001f&#x27; || c &gt;= &#x27;\u007f&#x27;) &#123;</span><br><span class="line">                sb.append(String.format(&quot;\\u%04x&quot;, (int) c));</span><br><span class="line">            &#125; else &#123;</span><br><span class="line">                sb.append(c);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        return sb.toString();</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>代码说明：<br>1、在Api17之后可以通过WebSettings.getDefaultUserAgent(context)获取，但是经过测试极个别手机会出现找不到类的情况，因此try-catch一下，那么第二种方式是System.getProperty(“http.agent”),这两种方式有什么不同呢？从结果上来看是第一种得到的信息更全一点；<br>第一种：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Mozilla/5.0 (Linux; Android 6.0.1; MI 4LTE Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) </span><br><span class="line">Version/4.0 Chrome/51.0.2704.81 Mobile Safari/537.36</span><br></pre></td></tr></table></figure>

<p>第二种：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Dalvik/2.1.0 (Linux; U; Android 6.0.1; MI 4LTE MIUI/6.10.13)</span><br></pre></td></tr></table></figure>
<p>2、在一些国产手机上面这个User-Agent里面会包含中文，就会报错</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">java.lang.IllegalArgumentException: Unexpected char 0x7231 at 33 in User-Agent value: Mozilla/5.0 (Linux; Android 5.1; 爱国者-X86 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36</span><br><span class="line">at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2367)</span><br><span class="line">at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2419)</span><br><span class="line">at android.app.ActivityThread.access$800(ActivityThread.java:151)</span><br><span class="line">at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342)</span><br><span class="line">at android.os.Handler.dispatchMessage(Handler.java:110)</span><br><span class="line">at android.os.Looper.loop(Looper.java:193)</span><br><span class="line">at android.app.ActivityThread.main(ActivityThread.java:5323)</span><br><span class="line">at java.lang.reflect.Method.invokeNative(Native Method)</span><br><span class="line">at java.lang.reflect.Method.invoke(Method.java:515)</span><br><span class="line">at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828)</span><br><span class="line">at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)</span><br><span class="line">at dalvik.system.NativeStart.main(Native Method)</span><br><span class="line">Caused by: java.lang.IllegalArgumentException: Unexpected char 0x7231 at 33 in User-Agent value: Mozilla/5.0 </span><br><span class="line">(Linux; Android 5.1; 爱国者-X86 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36</span><br><span class="line">at okhttp3.Headers$Builder.checkNameAndValue(Headers.java:320)</span><br><span class="line">at okhttp3.Headers$Builder.add(Headers.java:270)</span><br><span class="line">at okhttp3.Request$Builder.addHeader(Request.java:175)</span><br></pre></td></tr></table></figure>

<p>什么原因引起的呢？okhttp3.Headers$Builder.checkNameAndValue进到这个方法里面可以看到okhttp对中文进行了过滤，如果不符合条件就抛出异常IllegalArgumentException</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">private void checkNameAndValue(String name, String value) &#123;</span><br><span class="line">      if (name == null) throw new NullPointerException(&quot;name == null&quot;);</span><br><span class="line">      if (name.isEmpty()) throw new IllegalArgumentException(&quot;name is empty&quot;);</span><br><span class="line">      for (int i = 0, length = name.length(); i &lt; length; i++) &#123;</span><br><span class="line">        char c = name.charAt(i);</span><br><span class="line">        if (c &lt;= &#x27;\u001f&#x27; || c &gt;= &#x27;\u007f&#x27;) &#123;</span><br><span class="line">          throw new IllegalArgumentException(Util.format(</span><br><span class="line">              &quot;Unexpected char %#04x at %d in header name: %s&quot;, (int) c, i, name));</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      if (value == null) throw new NullPointerException(&quot;value == null&quot;);</span><br><span class="line">      for (int i = 0, length = value.length(); i &lt; length; i++) &#123;</span><br><span class="line">        char c = value.charAt(i);</span><br><span class="line">        if (c &lt;= &#x27;\u001f&#x27; || c &gt;= &#x27;\u007f&#x27;) &#123;</span><br><span class="line">          throw new IllegalArgumentException(Util.format(</span><br><span class="line">              &quot;Unexpected char %#04x at %d in %s value: %s&quot;, (int) c, i, name, value));</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>因此上段代码才会对返回结果进行过滤，如果不符合条件，会进行转码。</p>
<p>0x01-给Okhttp设置User-Agent</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Request request = new Request.Builder().url(url).removeHeader(&quot;User-Agent&quot;).addHeader(&quot;User-Agent&quot;,</span><br><span class="line">                getUserAgent()).build();</span><br><span class="line">httpClient.newCall(request).enqueue(handler);</span><br></pre></td></tr></table></figure>
<p>然后看下需求，后台要求传入<code>设备类型/APP版本号/设备型号/系统版本</code> 这样的字段。那么就可以开始了。<br>先分享一个工具类。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 系统工具类</span><br><span class="line"> */</span><br><span class="line">public class SystemUtil &#123;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取当前手机系统语言。</span><br><span class="line">     *</span><br><span class="line">     * @return 返回当前系统语言。例如：当前设置的是“中文-中国”，则返回“zh-CN”</span><br><span class="line">     */</span><br><span class="line">    public static String getSystemLanguage() &#123;</span><br><span class="line">        return Locale.getDefault().getLanguage();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取当前系统上的语言列表(Locale列表)</span><br><span class="line">     *</span><br><span class="line">     * @return  语言列表</span><br><span class="line">     */</span><br><span class="line">    public static Locale[] getSystemLanguageList() &#123;</span><br><span class="line">        return Locale.getAvailableLocales();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取当前手机系统版本号</span><br><span class="line">     *</span><br><span class="line">     * @return  系统版本号</span><br><span class="line">     */</span><br><span class="line">    public static String getSystemVersion() &#123;</span><br><span class="line">        return android.os.Build.VERSION.RELEASE;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取手机型号</span><br><span class="line">     *</span><br><span class="line">     * @return  手机型号</span><br><span class="line">     */</span><br><span class="line">    public static String getSystemModel() &#123;</span><br><span class="line">        return android.os.Build.MODEL;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取手机厂商</span><br><span class="line">     *</span><br><span class="line">     * @return  手机厂商</span><br><span class="line">     */</span><br><span class="line">    public static String getDeviceBrand() &#123;</span><br><span class="line">        return android.os.Build.BRAND;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取APP版本</span><br><span class="line">     * @param context</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    public static String getVersionName(Context context) &#123;</span><br><span class="line">        PackageManager packageManager = context.getPackageManager();</span><br><span class="line">        PackageInfo packageInfo;</span><br><span class="line">        String versionName = &quot;&quot;;</span><br><span class="line">        try &#123;</span><br><span class="line">            packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);</span><br><span class="line">            versionName = packageInfo.versionName;</span><br><span class="line">        &#125; catch (PackageManager.NameNotFoundException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        return versionName;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>然后，有了工具类就可以设置UA了，</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">    private static String getUserAgent(Context context) &#123;</span><br><span class="line">        String userAgent = &quot;&quot;;</span><br><span class="line">//        APP版本</span><br><span class="line">        String versionName = SystemUtil.getVersionName(context);</span><br><span class="line">//        手机型号</span><br><span class="line">        String systemModel = SystemUtil.getSystemModel();</span><br><span class="line">//        系统版本</span><br><span class="line">        String systemVersion = SystemUtil.getSystemVersion();</span><br><span class="line">        String deviceBrand = SystemUtil.getDeviceBrand();</span><br><span class="line">        userAgent = &quot;Android/&quot; + versionName + &quot;/&quot; + deviceBrand + &quot;&quot; + systemModel + &quot;/&quot; + systemVersion;</span><br><span class="line">        return userAgent;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>然后给Okhttp设置给Okhttp设置User-Agent</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Request request = new Request.Builder().url(url).removeHeader(&quot;User-Agent&quot;).addHeader(&quot;User-Agent&quot;,</span><br><span class="line">                getUserAgent()).build();</span><br><span class="line">httpClient.newCall(request).enqueue(handler);</span><br></pre></td></tr></table></figure>

<p>至此，已经完成。</p>
<p>部分内容来自简书。<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/ddbe8c637fc5">Okhttp设置User-Agent你可能没遇到的坑</a></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://vchao.top/2021/08/25/APP%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%EF%BC%9A%E4%BD%BF%E7%94%A8LeakCanary%E5%87%8F%E5%B0%91%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="vchao">
      <meta itemprop="description" content="怀揣好奇，梦想改变世界的菜鸟极客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="乘风破浪">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/08/25/APP%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%EF%BC%9A%E4%BD%BF%E7%94%A8LeakCanary%E5%87%8F%E5%B0%91%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2/" class="post-title-link" itemprop="url">APP内存优化：使用LeakCanary减少内存泄露</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-08-25 22:42:47 / 修改时间：22:37:20" itemprop="dateCreated datePublished" datetime="2021-08-25T22:42:47+08:00">2021-08-25</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><blockquote>
<p>看本篇文章之前，得首先了解下什么是内存泄露。还没接触过的朋友，建议先去了解一下。 <a target="_blank" rel="noopener" href="https://www.jianshu.com/p/65f914e6a2f8">https://www.jianshu.com/p/65f914e6a2f8</a></p>
</blockquote>
<p>简而言之：<br>内存泄漏过多会导致OOM，从而使APP崩溃。因此内存泄露向来都是内存优化的重点。避免、发现和解决内存泄漏是APP优化中尤为重要的一环。<br>本文即为介绍通过LeakCanary发现和解决内存泄露。</p>
<h1 id="一、简介"><a href="#一、简介" class="headerlink" title="一、简介"></a>一、简介</h1><p>LeakCanary是一个可视化的内存泄露分析工具，由Square公司基于MAT开源。与其他内存检测工具相比，LeakCanary学习成本低，易于发现问题，十分适合刚接触内存优化的同学学习。<br>但需要注意的是，LeakCanary并不能检测出来所有的内存泄漏，因此想深度优化的话，还需要配合其它工具一起使用，本文先略此不表。</p>
<h1 id="二、使用"><a href="#二、使用" class="headerlink" title="二、使用"></a>二、使用</h1><p>1、 首先需要读写权限，因为LeakCanary需要生成hprof文件，保存在SD卡里面，因此需要先申请权限</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;!– SDCard中创建与删除文件权限 –&gt;</span><br><span class="line"><span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">“android.permission.MOUNT_UNMOUNT_FILESYSTEMS”/</span>&gt;</span></span><br><span class="line">&lt;!– 向SDCard写入数据权限 –&gt;</span><br><span class="line"><span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">“android.permission.WRITE_EXTERNAL_STORAGE”/</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>2、在app build.gradle 中加入引用：</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">dependencies</span> &#123;</span><br><span class="line">    debugCompile <span class="string">&#x27;com.squareup.leakcanary:leakcanary-android:1.5&#x27;</span></span><br><span class="line">    releaseCompile <span class="string">&#x27;com.squareup.leakcanary:leakcanary-android-no-op:1.5&#x27;</span></span><br><span class="line">    testCompile <span class="string">&#x27;com.squareup.leakcanary:leakcanary-android-no-op:1.5&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>3、在 Application 中：<br><strong>简单使用</strong><br>如果要求比较低，只需要能够检测Activity的内存泄漏，代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//检测Activity的内存泄漏</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyApplication</span> <span class="keyword">extends</span> <span class="title">Application</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">super</span>.onCreate();</span><br><span class="line">    <span class="keyword">if</span> (LeakCanary.isInAnalyzerProcess(<span class="keyword">this</span>)) &#123;</span><br><span class="line">      <span class="comment">// This process is dedicated to LeakCanary for heap analysis.</span></span><br><span class="line">      <span class="comment">// You should not init your app in this process.</span></span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    LeakCanary.install(<span class="keyword">this</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如果当前的进程是用来给LeakCanary 进行堆分析的则return，否则会执行LeakCanary的install方法。这样我们就可以使用LeakCanary了，如果检测到某个Activity 有内存泄露，LeakCanary 就会给出提示。</p>
<p><strong>高级使用</strong><br>如果除了Activity的内存泄漏，还需要检测其他类的内存泄漏，那么可以使用RefWatcher来进行监控。代码如下所示：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyApplication</span> <span class="keyword">extends</span> <span class="title">Application</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> RefWatcher refWatcher;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate();</span><br><span class="line">        refWatcher= setupLeakCanary();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> RefWatcher <span class="title">setupLeakCanary</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (LeakCanary.isInAnalyzerProcess(<span class="keyword">this</span>)) &#123;</span><br><span class="line">            <span class="keyword">return</span> RefWatcher.DISABLED;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> LeakCanary.install(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> RefWatcher <span class="title">getRefWatcher</span><span class="params">(Context context)</span> </span>&#123;</span><br><span class="line">        MyApplication myApplication = (MyApplication) context.getApplicationContext();</span><br><span class="line">        <span class="keyword">return</span> myApplication.refWatcher;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>install方法会返回RefWatcher用来监控对象，Application中还要提供getRefWatcher静态方法来返回全局RefWatcher。<br>然后，需要关注拿个页面，就重写对应页面的onDestory()方法，加上如下代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">RefWatcher refWatcher = MyApplication.getRefWatcher(<span class="keyword">this</span>);</span><br><span class="line">refWatcher.watch(<span class="keyword">this</span>);</span><br></pre></td></tr></table></figure>

<p>4、运行</p>
<p>像往常一样运行程序后，会在界面生成一个名为Leaks的应用图标。接下来去执行APP的操作，如果发生了内存泄露，就会闪出一个提示框，提示“Dumping memory app will freeze.Brrrr.”,Notification也会有显示，这时点击桌面的Leaks图标，即可查看到详细的内存泄露列表以及信息。</p>
<p><img src="https://img-blog.csdnimg.cn/20190909164504559.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly92Y2hhby5ibG9nLmNzZG4ubmV0,size_16,color_FFFFFF,t_70" alt="leaks"><br>总结：</p>
<p>LeakCanary对于内存泄漏的检测非常有效，但也并不是所有的内存泄漏都能检测出来。</p>
<p>&lt;1&gt;无法检测出Service中的内存泄漏问题</p>
<p>&lt;2&gt;如果最底层的MainActivity一直未走onDestroy生命周期(它在Activity栈的最底层)，无法检测出它的调用栈的内存泄漏。</p>
<p>所以说LeakCanary针对Activity/Fragment的内存泄漏检测非常好用，但是对于以上检测不到的情况，还得配合Android Monitor + MAT 来分析。</p>
<p>参考：<br><a target="_blank" rel="noopener" href="https://www.jianshu.com/p/70b8c87ea877">https://www.jianshu.com/p/70b8c87ea877</a><br><a target="_blank" rel="noopener" href="https://www.jianshu.com/p/6d6af494cd26">https://www.jianshu.com/p/6d6af494cd26</a><br><a target="_blank" rel="noopener" href="http://liuwangshu.cn/application/performance/ram-6-leakcanary.html">http://liuwangshu.cn/application/performance/ram-6-leakcanary.html</a><br><a target="_blank" rel="noopener" href="https://www.jianshu.com/p/3f1a1cc1e964">https://www.jianshu.com/p/3f1a1cc1e964</a></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://vchao.top/2021/08/25/Android%E8%A7%A3%E5%86%B3%E5%8D%A1%E9%A1%BF%EF%BC%8C%E4%BB%8E%E9%81%BF%E5%85%8DOverdraw%E5%BC%80%E5%A7%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="vchao">
      <meta itemprop="description" content="怀揣好奇，梦想改变世界的菜鸟极客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="乘风破浪">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/08/25/Android%E8%A7%A3%E5%86%B3%E5%8D%A1%E9%A1%BF%EF%BC%8C%E4%BB%8E%E9%81%BF%E5%85%8DOverdraw%E5%BC%80%E5%A7%8B/" class="post-title-link" itemprop="url">Android解决卡顿，从避免Overdraw开始</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-08-25 22:42:47 / 修改时间：22:37:20" itemprop="dateCreated datePublished" datetime="2021-08-25T22:42:47+08:00">2021-08-25</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h4 id="什么是Overdraw？"><a href="#什么是Overdraw？" class="headerlink" title="什么是Overdraw？"></a>什么是Overdraw？</h4><p>Overdraw就是过度绘制，是指在一帧的时间内（16.67ms）像素被绘制了多次，理论上一个像素每次只绘制一次是最优的，但是由于重叠的布局导致一些像素会被多次绘制，而每次绘制都会对应到CPU的一组绘图命令和GPU的一些操作，当这个操作耗时超过16.67ms时，就会出现掉帧现象，也就是我们所说的卡顿，所以对重叠不可见元素的重复绘制会产生额外的开销，需要尽量减少Overdraw的发生。<br>Android提供了测量Overdraw的选项，在开发者选项－调试GPU过度绘制（Show GPU Overdraw），打开选项就可以看到当前页面Overdraw的状态，就可以观察屏幕的绘制状态。该工具会使用三种不同的颜色绘制屏幕，来指示overdraw发生在哪里以及程度如何，其中：<br>没有颜色： 意味着没有overdraw。像素只画了一次。<br>蓝色： 意味着overdraw 1倍。像素绘制了两次。大片的蓝色还是可以接受的（若整个窗口是蓝色的，可以摆脱一层）。<br>绿色： 意味着overdraw 2倍。像素绘制了三次。中等大小的绿色区域是可以接受的但你应该尝试优化、减少它们。<br>浅红： 意味着overdraw 3倍。像素绘制了四次，小范围可以接受。<br>暗红： 意味着overdraw 4倍。像素绘制了五次或者更多。这是错误的，要修复它们。</p>
<p>那么我们怎么来消灭overdraw呢？总的原则就是：尽量避免重叠不可见元素的绘制，基于这个原则，我们大概可以想出以下几招：</p>
<h4 id="第一招：合理选择控件容器"><a href="#第一招：合理选择控件容器" class="headerlink" title="第一招：合理选择控件容器"></a>第一招：合理选择控件容器</h4><p>既然overdraw是因为重复绘制了同一片区域的像素点，那我们首先想到的是解决布局问题。Android提供的Layout控件主要包括LinearLayout、TableLayout、FrameLayout、RelativeLayout。俗话说条条大路通罗马，同一个界面我们可以使用不同的容器控件来表达，但是各个容器控件描述界面的复杂度是不一样的。一般来说LinearLayout最易，RelativeLayout较复杂。但是尺有所短，寸有所长，LinearLayout只能用来描述一个方向上连续排列的控件，而RelativeLayout几乎可以用于描述任意复杂度的界面。但是我又要说但是了，表达能力越强的容器控件，性能往往略低一些，因为系统需要将更多的时间花在计算子控件的位置上。综上所述：<strong>LinearLayout易用，效率高，表达能力有限。RelativeLayout复杂，表达能力强，效率稍逊。</strong><br>那么对于同一界面而言，作为开发者考虑是使用尽量少的、表达能力强的RelativeLayout作为容器，还是选择多个、表达能力稍弱的LinearLayout来展示。从减少overdraw的角度来看，LinearLayout会增加控件数的层级，自然是RelativeLayout更优，但是当某一界面在使用LinearLayout并不会比RelativeLayout带来更多的控件数和控件层级时，LinearLayout则是首选。所以在表达界面的时候，作为一个有前瞻性的开发者要根据实际情况来选择合适容器控件，在保证性能的同时，尽量避免overdraw。</p>
<h4 id="第二招：去掉window的默认背景"><a href="#第二招：去掉window的默认背景" class="headerlink" title="第二招：去掉window的默认背景"></a>第二招：去掉window的默认背景</h4><p>当我们使用了Android自带的一些主题时，window会被默认添加一个纯色的背景，这个背景是被DecorView持有的。当我们的自定义布局时又添加了一张背景图或者设置背景色，那么DecorView的background此时对我们来说是无用的，但是它会产生一次Overdraw，带来绘制性能损耗。<br>去掉window的背景可以在onCreate()中setContentView()之后调用</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">getWindow().setBackgroundDrawable(null); </span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>或者在theme中添加</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">android:windowbackground=&quot;null&quot;；</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="第三招：去掉其他不必要的背景"><a href="#第三招：去掉其他不必要的背景" class="headerlink" title="第三招：去掉其他不必要的背景"></a>第三招：去掉其他不必要的背景</h4><p>有时候为了方便会先给Layout设置一个整体的背景，再给子View设置背景，这里也会造成重叠，如果子View宽度mach_parent，可以看到完全覆盖了Layout的一部分，这里就可以通过分别设置背景来减少重绘。再比如如果采用的是selector的背景，将normal状态的color设置为“@android:color/transparent”,也同样可以解决问题。这里只简单举两个例子，我们在开发过程中的一些习惯性思维定式会带来不经意的Overdraw，所以开发过程中我们为某个View或者ViewGroup设置背景的时候，先思考下是否真的有必要，或者思考下这个背景能不能分段设置在子View上，而不是图方便直接设置在根View上。</p>
<h4 id="第四招：ClipRect-amp-QuickReject"><a href="#第四招：ClipRect-amp-QuickReject" class="headerlink" title="第四招：ClipRect &amp; QuickReject"></a>第四招：ClipRect &amp; QuickReject</h4><p>为了解决Overdraw的问题，Android系统会通过避免绘制那些完全不可见的组件来尽量减少消耗。但是不幸的是，对于那些过于复杂的自定义的View(通常重写了onDraw方法)，Android系统无法检测在onDraw里面具体会执行什么操作，系统无法监控并自动优化，也就无法避免Overdraw了。但是我们可以通过canvas.clipRect()来帮助系统识别那些可见的区域。这个方法可以指定一块矩形区域，只有在这个区域内才会被绘制，其他的区域会被忽视。这个API可以很好的帮助那些有多组重叠组件的自定义View来控制显示的区域。同时clipRect方法还可以帮助节约CPU与GPU资源，在clipRect区域之外的绘制指令都不会被执行，那些部分内容在矩形区域内的组件，仍然会得到绘制。除了clipRect方法之外，我们还可以使用canvas.quickreject()来判断是否没和某个矩形相交，从而跳过那些非矩形区域内的绘制操作。</p>
<h4 id="第五招：ViewStub"><a href="#第五招：ViewStub" class="headerlink" title="第五招：ViewStub"></a>第五招：ViewStub</h4><p>ViewStub是个什么东西？一句话总结：<strong>高效占位符。</strong><br>我们经常会遇到这样的情况，运行时动态根据条件来决定显示哪个View或布局。常用的做法是把View都写在上面，先把它们的可见性都设为View.GONE，然后在代码中动态的更改它的可见性。这样的做法的优点是逻辑简单而且控制起来比较灵活。但是它的缺点就是，耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate，也就是说仍然会创建对象，会被实例化，会被设置属性。也就是说，会耗费内存等资源。<br>推荐的做法是使用android.view.ViewStub，ViewStub是一个轻量级的View，它一个看不见的，不占布局位置，占用资源非常小的控件。可以为ViewStub指定一个布局，在Inflate布局的时候，只有ViewStub会被初始化，然后当ViewStub被设置为可见的时候，或是调用了ViewStub.inflate()的时候，ViewStub所向的布局就会被Inflate和实例化，然后ViewStub的布局属性都会传给它所指向的布局。这样，就可以使用ViewStub来方便的在运行时，要还是不要显示某个布局。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&lt;ViewStub</span><br><span class="line">    android:id=&quot;@+id/stub_view&quot;</span><br><span class="line">    android:inflatedId=&quot;@+id/panel_stub&quot;</span><br><span class="line">    android:layout=&quot;@layout/progress_overlay&quot;</span><br><span class="line">    android:layout_width=&quot;fill_parent&quot;</span><br><span class="line">    android:layout_height=&quot;wrap_content&quot;</span><br><span class="line">    android:layout_gravity=&quot;bottom&quot; /&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>当你想加载布局时，可以使用下面其中一种方法：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">((ViewStub) findViewById(R.id.stub_view)).setVisibility(View.VISIBLE);</span><br><span class="line">View importPanel = ((ViewStub) findViewById(R.id.stub_view)).inflate();</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="第六招：Merge"><a href="#第六招：Merge" class="headerlink" title="第六招：Merge"></a>第六招：Merge</h4><p>Merge标签有什么用呢？简单粗暴点回答：<strong>干掉一个view层级。</strong><br>Merge的作用很明显，但是也有一些使用条件的限制。有两种情况下我们可以使用Merge标签来做容器控件。第一种子视图不需要指定任何针对父视图的布局属性，就是说父容器仅仅是个容器，子视图只需要直接添加到父视图上用于显示就行。另外一种是假如需要在LinearLayout里面嵌入一个布局（或者视图），而恰恰这个布局（或者视图）的根节点也是LinearLayout，这样就多了一层没有用的嵌套，无疑这样只会拖慢程序速度。而这个时候如果我们使用merge根标签就可以避免那样的问题。另外Merge只能作为XML布局的根标签使用，当Inflate以<merge />开头的布局文件时，必须指定一个父ViewGroup，并且必须设定attachToRoot为true。<br>举个简单的例子吧：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;RelativeLayout </span><br><span class="line">xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot; </span><br><span class="line">xmlns:tools=&quot;http://schemas.android.com/tools&quot; </span><br><span class="line">android:layout_width=&quot;match_parent&quot; </span><br><span class="line">android:layout_height=&quot;match_parent&quot; &gt; </span><br><span class="line">&lt;TextView </span><br><span class="line">android:layout_width=&quot;wrap_content&quot;  </span><br><span class="line">android:layout_height=&quot;wrap_content&quot; </span><br><span class="line">android:text=&quot;merge标签使用&quot; /&gt;</span><br><span class="line">&lt;/RelativeLayout&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>把上面这个XML加载到页面中，布局层级是RelativeLayout-TextView。但是采用下面的方式，把RelativeLayout提换成merge，RelativeLayout这一层级就被干掉了。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;merge</span><br><span class="line">xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot; </span><br><span class="line">xmlns:tools=&quot;http://schemas.android.com/tools&quot; </span><br><span class="line">android:layout_width=&quot;match_parent&quot; </span><br><span class="line">android:layout_height=&quot;match_parent&quot; &gt;</span><br><span class="line">&lt;TextView  </span><br><span class="line">android:layout_width=&quot;wrap_content&quot; </span><br><span class="line">android:layout_height=&quot;wrap_content&quot; </span><br><span class="line"> android:text=&quot;merge标签使用&quot; /&gt;</span><br><span class="line">&lt;/merge&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="第七招：善用draw9patch"><a href="#第七招：善用draw9patch" class="headerlink" title="第七招：善用draw9patch"></a>第七招：善用draw9patch</h4><p>给ImageView加一个边框，你肯定遇到过这种需求，通常在ImageView后面设置一张背景图，露出边框便完美解决问题，此时这个ImageView，设置了两层drawable，底下一层仅仅是为了作为图片的边框而已。但是两层drawable的重叠区域去绘制了两次，导致overdraw。<br>优化方案： 将背景drawable制作成draw9patch，并且将和前景重叠的部分设置为透明。由于Android的2D渲染器会优化draw9patch中的透明区域，从而优化了这次overdraw。 但是背景图片必须制作成draw9patch才行，因为Android 2D渲染器只对draw9patch有这个优化，否则，一张普通的Png，就算你把中间的部分设置成透明，也不会减少这次overdraw。</p>
<h4 id="第八招：慎用Alpha"><a href="#第八招：慎用Alpha" class="headerlink" title="第八招：慎用Alpha"></a>第八招：慎用Alpha</h4><p>假如对一个View做Alpha转化，需要先将View绘制出来，然后做Alpha转化，最后将转换后的效果绘制在界面上。通俗点说，做Alpha转化就需要对当前View绘制两遍，可想而知，绘制效率会大打折扣，耗时会翻倍，所以Alpha还是慎用。<br>如果一定做Alpha转化的话，可以采用缓存的方式。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">view.setLayerType(LAYER_TYPE_HARDWARE);</span><br><span class="line">doSmoeThing();</span><br><span class="line">view.setLayerType(LAYER_TYPE_NONE);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>通过setLayerType方式可以将当前界面缓存在GPU中，这样不需要每次绘制原始界面，但是GPU内存是相当宝贵的，所以用完要马上释放掉。</p>
<h4 id="第九招：避免“OverDesign”"><a href="#第九招：避免“OverDesign”" class="headerlink" title="第九招：避免“OverDesign”"></a>第九招：避免“OverDesign”</h4><p>overdraw会给APP带来不好的体验，overdraw产生的原因无外乎：复杂的Layout层级，重叠的View，重叠的背景这几种。开发人员无节制的View堆砌，究其根本无非是产品无节制的需求设计。有道是“由俭入奢易，由奢入俭难”，很多APP披着过度设计的华丽外衣，却忘了简单易用才是王道的本质，纷繁复杂的设计并不会给用户带来好的体验，反而会让用户有压迫感，产品本身也有可能因此变得卡顿。当然，一切抛开业务谈优化都是空中楼阁，这就需要产品设计也要有一个权衡，在复杂的业务逻辑与简单易用的界面展现中做一个平衡，而不是一味的OverDesign。</p>
<p>本文转载，原文信息如下：<br>作者：尹star<br>链接：<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/145fc61011cd">https://www.jianshu.com/p/145fc61011cd</a><br>來源：简书<br>著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://vchao.top/2021/08/25/Android%E8%87%AA%E5%AE%9A%E4%B9%89View-%E5%80%92%E8%AE%A1%E6%97%B6%E6%8E%A7%E4%BB%B6%EF%BC%88%E5%8F%AF%E8%87%AA%E5%8A%A8%E7%BB%A7%E7%BB%AD%EF%BC%8C%E7%9F%AB%E6%AD%A3%E6%97%B6%E9%97%B4%EF%BC%89/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="vchao">
      <meta itemprop="description" content="怀揣好奇，梦想改变世界的菜鸟极客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="乘风破浪">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/08/25/Android%E8%87%AA%E5%AE%9A%E4%B9%89View-%E5%80%92%E8%AE%A1%E6%97%B6%E6%8E%A7%E4%BB%B6%EF%BC%88%E5%8F%AF%E8%87%AA%E5%8A%A8%E7%BB%A7%E7%BB%AD%EF%BC%8C%E7%9F%AB%E6%AD%A3%E6%97%B6%E9%97%B4%EF%BC%89/" class="post-title-link" itemprop="url">Android自定义View-倒计时控件（可自动继续，矫正时间）</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-08-25 22:42:47 / 修改时间：22:37:20" itemprop="dateCreated datePublished" datetime="2021-08-25T22:42:47+08:00">2021-08-25</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h1><p>项目中需要用到倒计时View，因为需求需要，所以不能只依靠本地计时。还需要网络请求数据之后，矫正时间。</p>
<p>所以本文的目标如下：</p>
<ul>
<li>自定义字体</li>
<li>依赖网络的倒计时</li>
<li>时间矫正</li>
<li>倒计时的自动更新</li>
</ul>
<p>最终效果如下：</p>
<p><img src="C:\Users\zly\Desktop\倒计时.png" alt="倒计时"></p>
<h1 id="分析"><a href="#分析" class="headerlink" title="分析"></a>分析</h1><p>通过自定义控件去实现，然后通过HashMap存储对应奖期以及倒计时信息，然后通过定时的网络请求，去矫正计时。</p>
<p>因此本文设计控件继承自AppCompatTextView， 增加了设置初始时间，开始计时，更新计时，停止计时，取消计时，矫正计时，设置字体等若干方法。</p>
<h1 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h1><h2 id="加载自定义字体"><a href="#加载自定义字体" class="headerlink" title="加载自定义字体"></a>加载自定义字体</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 加载自定义字体</span></span><br><span class="line">Typeface TEXT_TYPE;</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    TEXT_TYPE = Typeface.createFromAsset(context.getAssets(), <span class="string">&quot;fonts/Quartz_Regular.ttf&quot;</span>);</span><br><span class="line">&#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">    LogUtils.e(<span class="string">&quot;加载第三方字体失败。&quot;</span>);</span><br><span class="line">    TEXT_TYPE = <span class="keyword">null</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (TEXT_TYPE != <span class="keyword">null</span>) &#123;</span><br><span class="line">    setTypeface(TEXT_TYPE);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="开始计时"><a href="#开始计时" class="headerlink" title="开始计时"></a>开始计时</h2><p>开始计时，首先通过接口回调，对外暴露方法，方便进行开始前的准备工作。需要传入期次和结束时间两个参数。</p>
<p>更新时间通过handler去实现。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">start</span><span class="params">(<span class="keyword">final</span> <span class="keyword">int</span> term_no, <span class="keyword">final</span> <span class="keyword">long</span> end_time)</span> </span>&#123;</span><br><span class="line">    timeListener.timeStart();</span><br><span class="line"></span><br><span class="line">    contine_tag = <span class="keyword">true</span>;</span><br><span class="line">    <span class="keyword">this</span>.end_time = end_time;</span><br><span class="line">    <span class="keyword">this</span>.term_no = term_no;</span><br><span class="line">    <span class="keyword">if</span> (mTimerMap.get(term_no) == <span class="keyword">null</span>) &#123;</span><br><span class="line">        Timer timer = <span class="keyword">new</span> Timer();</span><br><span class="line">        Term_view_bean term_view_bean = <span class="keyword">new</span> Term_view_bean(timer, term_no, end_time);</span><br><span class="line">        mTimerMap.put(term_no, term_view_bean);</span><br><span class="line">        mTimerMap.get(term_no).getTimer().schedule(<span class="keyword">new</span> TimerTask() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                <span class="keyword">if</span> (contine_tag) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (is_over) &#123;</span><br><span class="line">                        <span class="keyword">this</span>.cancel();</span><br><span class="line">                        <span class="keyword">return</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                    mHandler.sendEmptyMessage(ticket_mode);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;, <span class="number">0</span>, <span class="number">1000</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="结束"><a href="#结束" class="headerlink" title="结束"></a>结束</h2><p>结束计时，共分为2种，取消指定期次，和取消全部期次。</p>
<blockquote>
<p>取消全部期次计时： 当不需要页面倒计时的时候调用，因为倒计时是采用Timer进行维护的，所以需要手动释放，以避免内存泄露相关事宜。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">stopAll</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Iterator it = mTimerMap.entrySet().iterator();</span><br><span class="line">            <span class="keyword">while</span> (it.hasNext()) &#123;</span><br><span class="line">                Map.Entry entry = (Map.Entry) it.next();</span><br><span class="line">                <span class="keyword">int</span> key = (<span class="keyword">int</span>) entry.getKey();</span><br><span class="line">                Term_view_bean bean = (Term_view_bean) entry.getValue();</span><br><span class="line">                bean.getTimer().cancel();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        contine_tag = <span class="keyword">false</span>;</span><br><span class="line">        is_over = <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">   </span><br></pre></td></tr></table></figure>

<blockquote>
<p>取消指定期次计时： 某一个期次奖期结束，根据期次号或者存储的值进行停止</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">   </span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">stop</span><span class="params">(<span class="keyword">int</span> position_term_no)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (mTimerMap.get(position_term_no) != <span class="keyword">null</span>) &#123;</span><br><span class="line">            mTimerMap.get(position_term_no).getTimer().cancel();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">stopSaveValue</span><span class="params">(<span class="keyword">int</span> value)</span> </span>&#123;</span><br><span class="line">    Iterator it = mTimerMap.entrySet().iterator();</span><br><span class="line">    <span class="keyword">while</span> (it.hasNext()) &#123;</span><br><span class="line">        Map.Entry entry = (Map.Entry) it.next();</span><br><span class="line">        <span class="keyword">int</span> key = (<span class="keyword">int</span>) entry.getKey();</span><br><span class="line">        <span class="keyword">if</span> (key != value) &#123;</span><br><span class="line">            Term_view_bean bean = (Term_view_bean) entry.getValue();</span><br><span class="line">            bean.getTimer().cancel();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="时间显示格式化"><a href="#时间显示格式化" class="headerlink" title="时间显示格式化"></a>时间显示格式化</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 时间显示格式化</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> second</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> String <span class="title">second2TimeSecond</span><span class="params">(<span class="keyword">long</span> second)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">long</span> days = second / (<span class="number">3600</span> * <span class="number">24</span>);</span><br><span class="line">    <span class="keyword">long</span> hours = (second / <span class="number">3600</span>) % <span class="number">24</span>;</span><br><span class="line">    <span class="keyword">long</span> minutes = (second % <span class="number">3600</span>) / <span class="number">60</span>;</span><br><span class="line">    <span class="keyword">long</span> seconds = second % <span class="number">60</span>;</span><br><span class="line"></span><br><span class="line">    String showTime = <span class="string">&quot;&quot;</span>;</span><br><span class="line">    <span class="keyword">if</span> (days &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        showTime = days + <span class="string">&quot;天 &quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (hours &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (hours &lt; <span class="number">10</span>) &#123;</span><br><span class="line">            showTime += <span class="string">&quot;0&quot;</span> + hours + <span class="string">&quot;时 &quot;</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            showTime += hours + <span class="string">&quot;时 &quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (minutes &lt; <span class="number">10</span>) &#123;</span><br><span class="line">        showTime += <span class="string">&quot;0&quot;</span> + minutes + <span class="string">&quot;:&quot;</span>;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        showTime += <span class="string">&quot;&quot;</span> + minutes + <span class="string">&quot;:&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (seconds &lt; <span class="number">10</span>) &#123;</span><br><span class="line">        showTime += <span class="string">&quot;0&quot;</span> + seconds;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        showTime += <span class="string">&quot;&quot;</span> + seconds;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> showTime;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="修正倒计时"><a href="#修正倒计时" class="headerlink" title="修正倒计时"></a>修正倒计时</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 修正当前倒计时信息</span><br><span class="line"> */</span><br><span class="line">public void updateTimer(final int term_no, final long end_time) &#123;</span><br><span class="line">    this.end_time = end_time;</span><br><span class="line">    this.term_no = term_no;</span><br><span class="line">    if (mTimerMap.get(term_no) == null) &#123;</span><br><span class="line">        start(term_no, end_time);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        mTimerMap.get(term_no).setEnd_time(end_time);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p>使用的时候，首先初始化，传入handler，然后定时进行网络请求即可呈现效果。</p>
<h1 id="完整代码"><a href="#完整代码" class="headerlink" title="完整代码"></a>完整代码</h1><p>完整代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CountdownTextView</span> <span class="keyword">extends</span> <span class="title">android</span>.<span class="title">support</span>.<span class="title">v7</span>.<span class="title">widget</span>.<span class="title">AppCompatTextView</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> what_count_down_k3 = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    Map&lt;Integer, Term_view_bean&gt; mTimerMap;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> term_no;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> ticket_mode;</span><br><span class="line">    <span class="keyword">private</span> TimeListener timeListener;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">long</span> end_time = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">boolean</span> contine_tag = <span class="keyword">true</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">boolean</span> is_over = <span class="keyword">false</span>;</span><br><span class="line">    <span class="keyword">private</span> Handler mHandler = <span class="keyword">new</span> Handler() &#123;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">handleMessage</span><span class="params">(android.os.Message msg)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">switch</span> (msg.what) &#123;</span><br><span class="line">                <span class="keyword">case</span> what_count_down_k3:<span class="comment">// 10 分钟一期</span></span><br><span class="line">					<span class="keyword">if</span> (end_time - TimeManager.getInstance().getServiceTime() &lt;= Config.K3_R006_Time_End_sale * <span class="number">1000</span>) &#123;                 </span><br><span class="line">                        timeListener.buyDown();</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">if</span> (end_time - TimeManager.getInstance().getServiceTime() &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">                        timeListener.timedown();</span><br><span class="line">                        <span class="keyword">while</span> (end_time - TimeManager.getInstance().getServiceTime() &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">                            term_no++;</span><br><span class="line">                            end_time += <span class="number">10</span> * <span class="number">60</span> * <span class="number">1000</span>;</span><br><span class="line">                        &#125;</span><br><span class="line">                        setTimeText();</span><br><span class="line">                        <span class="keyword">try</span> &#123;</span><br><span class="line">                            stopSaveValue(term_no);</span><br><span class="line">                        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">                            e.printStackTrace();</span><br><span class="line">                        &#125;</span><br><span class="line">                        start(term_no, end_time);</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        setTimeText();</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">CountdownTextView</span><span class="params">(Context context)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(context);</span><br><span class="line">        initTextType(context);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">CountdownTextView</span><span class="params">(Context context, AttributeSet attrs)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(context, attrs);</span><br><span class="line">        initTextType(context);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">CountdownTextView</span><span class="params">(Context context, AttributeSet attrs, <span class="keyword">int</span> defStyleAttr)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(context, attrs, defStyleAttr);</span><br><span class="line">        initTextType(context);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">setTimeText</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        setText(second2TimeSecond((end_time - TimeManager.getInstance().getServiceTime()) / <span class="number">1000</span>));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">initTextType</span><span class="params">(Context context)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 加载自定义字体</span></span><br><span class="line">        Typeface TEXT_TYPE;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            TEXT_TYPE = Typeface.createFromAsset(context.getAssets(), <span class="string">&quot;fonts/Quartz_Regular.ttf&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            LogUtils.e(<span class="string">&quot;加载第三方字体失败。&quot;</span>);</span><br><span class="line">            TEXT_TYPE = <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (TEXT_TYPE != <span class="keyword">null</span>) &#123;</span><br><span class="line">            setTypeface(TEXT_TYPE);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">(<span class="keyword">int</span> ticket_mode, TimeListener timeListener)</span> </span>&#123;</span><br><span class="line">        mTimerMap = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">        <span class="keyword">this</span>.timeListener = timeListener;</span><br><span class="line">        <span class="keyword">this</span>.ticket_mode = ticket_mode;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">start</span><span class="params">(<span class="keyword">final</span> <span class="keyword">int</span> term_no, <span class="keyword">final</span> <span class="keyword">long</span> end_time)</span> </span>&#123;</span><br><span class="line">        timeListener.timeStart();</span><br><span class="line"></span><br><span class="line">        contine_tag = <span class="keyword">true</span>;</span><br><span class="line">        <span class="keyword">this</span>.end_time = end_time;</span><br><span class="line">        <span class="keyword">this</span>.term_no = term_no;</span><br><span class="line">        <span class="keyword">if</span> (mTimerMap.get(term_no) == <span class="keyword">null</span>) &#123;</span><br><span class="line">            Timer timer = <span class="keyword">new</span> Timer();</span><br><span class="line">            Term_view_bean term_view_bean = <span class="keyword">new</span> Term_view_bean(timer, term_no, end_time);</span><br><span class="line">            mTimerMap.put(term_no, term_view_bean);</span><br><span class="line">            mTimerMap.get(term_no).getTimer().schedule(<span class="keyword">new</span> TimerTask() &#123;</span><br><span class="line">                <span class="meta">@Override</span></span><br><span class="line">                <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                    <span class="keyword">if</span> (contine_tag) &#123;</span><br><span class="line">                        <span class="keyword">if</span> (is_over) &#123;</span><br><span class="line">                            <span class="keyword">this</span>.cancel();</span><br><span class="line">                            <span class="keyword">return</span>;</span><br><span class="line">                        &#125;</span><br><span class="line">                        mHandler.sendEmptyMessage(ticket_mode);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;, <span class="number">0</span>, <span class="number">1000</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">stop</span><span class="params">(<span class="keyword">int</span> position_term_no)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (mTimerMap.get(position_term_no) != <span class="keyword">null</span>) &#123;</span><br><span class="line">            mTimerMap.get(position_term_no).getTimer().cancel();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">stopAll</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Iterator it = mTimerMap.entrySet().iterator();</span><br><span class="line">            <span class="keyword">while</span> (it.hasNext()) &#123;</span><br><span class="line">                Map.Entry entry = (Map.Entry) it.next();</span><br><span class="line">                <span class="keyword">int</span> key = (<span class="keyword">int</span>) entry.getKey();</span><br><span class="line">                Term_view_bean bean = (Term_view_bean) entry.getValue();</span><br><span class="line">                bean.getTimer().cancel();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        contine_tag = <span class="keyword">false</span>;</span><br><span class="line">        is_over = <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">stopSaveValue</span><span class="params">(<span class="keyword">int</span> value)</span> </span>&#123;</span><br><span class="line">        Iterator it = mTimerMap.entrySet().iterator();</span><br><span class="line">        <span class="keyword">while</span> (it.hasNext()) &#123;</span><br><span class="line">            Map.Entry entry = (Map.Entry) it.next();</span><br><span class="line">            <span class="keyword">int</span> key = (<span class="keyword">int</span>) entry.getKey();</span><br><span class="line">            <span class="keyword">if</span> (key != value) &#123;</span><br><span class="line">                Term_view_bean bean = (Term_view_bean) entry.getValue();</span><br><span class="line">                bean.getTimer().cancel();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 格式化</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> second</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> String <span class="title">second2TimeSecond</span><span class="params">(<span class="keyword">long</span> second)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">long</span> days = second / (<span class="number">3600</span> * <span class="number">24</span>);</span><br><span class="line">        <span class="keyword">long</span> hours = (second / <span class="number">3600</span>) % <span class="number">24</span>;</span><br><span class="line">        <span class="keyword">long</span> minutes = (second % <span class="number">3600</span>) / <span class="number">60</span>;</span><br><span class="line">        <span class="keyword">long</span> seconds = second % <span class="number">60</span>;</span><br><span class="line"></span><br><span class="line">        String showTime = <span class="string">&quot;&quot;</span>;</span><br><span class="line">        <span class="keyword">if</span> (days &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            showTime = days + <span class="string">&quot;天 &quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (hours &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (hours &lt; <span class="number">10</span>) &#123;</span><br><span class="line">                showTime += <span class="string">&quot;0&quot;</span> + hours + <span class="string">&quot;时 &quot;</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                showTime += hours + <span class="string">&quot;时 &quot;</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (minutes &lt; <span class="number">10</span>) &#123;</span><br><span class="line">            showTime += <span class="string">&quot;0&quot;</span> + minutes + <span class="string">&quot;:&quot;</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            showTime += <span class="string">&quot;&quot;</span> + minutes + <span class="string">&quot;:&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (seconds &lt; <span class="number">10</span>) &#123;</span><br><span class="line">            showTime += <span class="string">&quot;0&quot;</span> + seconds;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            showTime += <span class="string">&quot;&quot;</span> + seconds;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> showTime;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取当前奖期</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getTerm_no</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> term_no;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 修正当前倒计时信息</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">updateTimer</span><span class="params">(<span class="keyword">final</span> <span class="keyword">int</span> term_no, <span class="keyword">final</span> <span class="keyword">long</span> end_time)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.end_time = end_time;</span><br><span class="line">        <span class="keyword">this</span>.term_no = term_no;</span><br><span class="line">        <span class="keyword">if</span> (mTimerMap.get(term_no) == <span class="keyword">null</span>) &#123;</span><br><span class="line">            start(term_no, end_time);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            mTimerMap.get(term_no).setEnd_time(end_time);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">TimeListener</span> </span>&#123;</span><br><span class="line">        <span class="function"><span class="keyword">void</span> <span class="title">timedown</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">void</span> <span class="title">buyDown</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">void</span> <span class="title">timeStart</span><span class="params">()</span></span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="class"><span class="keyword">class</span> <span class="title">Term_view_bean</span> </span>&#123;</span><br><span class="line">        <span class="keyword">private</span> Timer timer;<span class="comment">// 定时器</span></span><br><span class="line">        <span class="keyword">private</span> <span class="keyword">int</span> integer;<span class="comment">// 奖期</span></span><br><span class="line">        <span class="keyword">private</span> <span class="keyword">long</span> end_time;<span class="comment">// 结束时间</span></span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">Term_view_bean</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">Term_view_bean</span><span class="params">(Timer timer, <span class="keyword">int</span> integer, <span class="keyword">long</span> end_time)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.timer = timer;</span><br><span class="line">            <span class="keyword">this</span>.integer = integer;</span><br><span class="line">            <span class="keyword">this</span>.end_time = end_time;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> Timer <span class="title">getTimer</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> timer;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setTimer</span><span class="params">(Timer timer)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.timer = timer;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getInteger</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> integer;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setInteger</span><span class="params">(<span class="keyword">int</span> integer)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.integer = integer;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">long</span> <span class="title">getEnd_time</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> end_time;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setEnd_time</span><span class="params">(<span class="keyword">long</span> end_time)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.end_time = end_time;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://vchao.top/2021/08/25/Android%E5%90%84%E4%B8%AA%E7%89%88%E6%9C%AC%E7%89%B9%E6%80%A7%E7%AE%80%E4%BB%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="vchao">
      <meta itemprop="description" content="怀揣好奇，梦想改变世界的菜鸟极客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="乘风破浪">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/08/25/Android%E5%90%84%E4%B8%AA%E7%89%88%E6%9C%AC%E7%89%B9%E6%80%A7%E7%AE%80%E4%BB%8B/" class="post-title-link" itemprop="url">Android各个版本特性简介</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-08-25 22:42:47 / 修改时间：22:37:20" itemprop="dateCreated datePublished" datetime="2021-08-25T22:42:47+08:00">2021-08-25</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <blockquote>
<p>俗话说，磨刀不误砍柴工。没错，今天就来聊点砍柴的事。由于Android系统更新速度快，导致市面上的Android系统版本不一（专业术语叫碎片化严重）。而作为程序开发者，必须尽量照顾到各种版本的系统，so……了解其各个版本的特性很有必要。（本文内容都是我查资料后，按照自己理解整理的，部分内容可能并不准确，还望见谅。但是大体无误，对写程序也不会有啥太大影响）</p>
</blockquote>
<p>Android是一个由Google和开放手持设备联盟共同开发发展的移动设备操作系统，其最早的一个版本Android 1.0 beta发布于2007年11月5日，至今已经发布了多个更新。这些更新版本都在前一个版本的基础上修复了Bug并且添加了前一个版本所没有的新功能。<br>##Android版本概述<br>Android操作系统曾有两个预发布的内部版本，它们的代号分别是铁臂阿童木（Astro）和发条机器人（Bender）。由于涉及到版权问题，从2009年5月开始，Android操作系统改用甜点来作为版本代号，这些版本按照大写字母的顺序来进行命名。<br>##Android logo形象<br>Android是一个全身绿色的机器人，颜色采用了PMS 376C和RGB中十六进制的#A4C639来绘制，这是Android操作系统的品牌象征。有时候，它会以纯文本的标志展示。Android的标志是由Ascender 公司设计的，其中的文本使用了Ascender公司专门制作的称之为“Google Droid字体”的字体。<br><img src="http://img.blog.csdn.net/20170510131647894?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmdfd2VpY2hhbw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="Android logo"></p>
<p>##Android版本和API Level对应关系</p>
<blockquote>
<p>随着版本的更迭，应用程序编程接口（API）等级不断发生。下面将目前为止所有API等级罗列出来，并与Android各版本一一对应。<br>API Level|Platform Version |VERSION_CODE|Time<br>——– | —————-|————|—-|—–<br>1|Android 1.0||2008年9月<br>2|Android 1.1 |Petit Four|<br>3|Android 1.5| Cupcake（纸杯蛋糕）|2009年4月30日<br>4|Android 1.6 |Donut（甜甜圈）|2009年9月15日<br>5|Android 2.0 |Éclair（闪电泡芙）|2009年10月26日<br>6|Android 2.0.1| Éclair|<br>7|Android 2.1 |Éclair|<br>8|Android 2.2 - 2.2.3 |Froyo（冻酸奶）|2010年5月20日<br>9|Android 2.3 - 2.3.2 |Gingerbread（姜饼）|2010年12月7日<br>10|Android 2.3.3-2.3.7 |Gingerbread|<br>11|Android 3.0 |Honeycomb（蜂巢）|2011年2月2日<br>12|Android 3.1 |Honeycomb|2011年5月11日<br>13|Android 3.2 |Honeycomb|2011年7月13日<br>14|Android 4.0 - 4.0.2 |Ice Cream Sandwich（冰激凌三明治）|2011年10月19日<br>15|Android 4.0.3 - 4.0.4| Ice Cream Sandwich|<br>16|Android 4.1 |Jelly Bean（果冻豆）|2012年6月28日<br>17|Android 4.2 |Jelly Bean|2012年10月30日<br>18|Android 4.3 |Jelly Bean|2012年10月30日<br>19|Android 4.4 |KitKat（奇巧巧克力）|2013年下半年<br>20|Android 4.4W||<br>21|Android 5.0 |Lollipop（棒棒糖）| 2014年11月3日<br>22|Android 5.1 |Lollipop|<br>23|Android 6.0 |Marshmallow（棉花糖）|2015年5月28日<br>24|Android 7.0 |Nougat（牛轧糖）|2016年8月22日</p>
</blockquote>
<p>##Android各个版本特性</p>
<blockquote>
<p>首先得说一下，下面的内容是依据百度百科里的内容写的，对其进行了精简。想看详细的请移步<a target="_blank" rel="noopener" href="http://baike.baidu.com/item/Android%E5%8E%86%E5%8F%B2%E7%89%88%E6%9C%AC">Android历史版本</a></p>
</blockquote>
<p>###Android 1.0</p>
<blockquote>
<p>2008年9月23日,发布Android操作系统中的第一个正式版本：Android 1.0（Astro“铁臂阿童木”）。全球第一台Android设备HTC Dream（G1）就是搭载Android 1.0操作系统，特性如下：</p>
</blockquote>
<ul>
<li>网页浏览器：可以完全还原并且显示HTML和XHTML的网页 – 并且可以通过多点触控对网页进行放大缩小。</li>
<li>照相机支持：支持照相机和摄像头，但是这个版本没有选项来改变相机的分辨率、白平衡、质量等等。</li>
<li>允许将应用程序图标放置到文件夹中，并且可以在主界面显示插件等东西。</li>
<li>Gmail, Google联系人,Google日历, Google地图、Google纵横以及Google街景 ,Google同步,Google搜索，Google Talk的支持。</li>
<li>多媒体播放器：负责管理、导入、拷贝和播放多媒体文件，但是不支持蓝牙耳机。</li>
<li>声音识别器可以允许用户通过说话来输入文本、拨打电话，能更好的帮助残疾人士。</li>
<li>YouTube内置YouTube在线应用程序。</li>
<li>其他应用程序：闹钟，计算器，电话，主界面，图库，壁纸以及设置。</li>
<li>支持Wi-Fi和蓝牙</li>
</ul>
<p>###Android 1.1</p>
<blockquote>
<p>2009年2月2日，Android 1.1（Bender“发条机器人”）发布，该版本只被预装在T-Mobile G1上。该版本处理了前一版本遗留的许多应用程序和系统的Bug，改进了API接口和添加了新的特性：</p>
</blockquote>
<ul>
<li>用户搜索企业和其他服务时，下方会显示出其他用户搜索时对该搜索信息的评价和留言。</li>
<li>加强了电话功能，改进了免提功能。</li>
<li>支持对邮件附件的保存和预览功能。</li>
<li>增加了长按任意界面弹出多选框的功能。</li>
</ul>
<p>###Android 1.5 Cupcake</p>
<blockquote>
<p>2009年4月17日Google正式推出其新一版的Android 1.5( Cupcake“纸杯蛋糕”)，新版本提升并修正了前一个版本里的许多功能，具体更新如下：</p>
</blockquote>
<ul>
<li>拍摄/播放视频，并支持上传到Youtube。</li>
<li>支持立体声蓝牙耳机，同时改善自动配对性能。</li>
<li>最新的采用WebKit技术的浏览器，支持复制/粘贴和页面中搜索。</li>
<li>GPS性能大大提高</li>
<li>提供屏幕虚拟键盘</li>
<li>主屏幕增加音乐播放器和相框widgets</li>
<li>应用程序自动随着手机旋转</li>
<li>短信、Gmail、日暦，浏览器的用户界面大幅改进，如Gmail可以批量删除邮件。</li>
<li>相机启动速度加快，拍摄图片可以直接上传到Picasa。</li>
<li>来电照片显示</li>
</ul>
<p>###Android 1.6 Donut</p>
<blockquote>
<p>2009年9月15日，Android 1.6（Donut 甜甜圈）软件开发工具包发布，该版本基于Linux 2.6.29内核。主要的更新如下：</p>
</blockquote>
<ul>
<li>重新设计的Android Market</li>
<li>手势支持</li>
<li>支持CDMA网络</li>
<li>文本转语音系统（Text-to-Speech）</li>
<li>快速搜索框</li>
<li>全新的拍照界面</li>
<li>查看应用程序耗电</li>
<li>支持虚拟私人网络（VPN）</li>
<li>支持更多的屏幕分辨率</li>
<li>支持OpenCore2媒体引擎</li>
<li>新增面向视觉或听觉困难人群的易用性插件</li>
</ul>
<p>###Android 2.0/2.1 Eclair</p>
<ul>
<li>新的浏览器的用户界面和支持HTML5</li>
<li>改进Google Maps 3.1.2</li>
<li>支持Microsoft Exchange</li>
<li>支持内置相机闪光灯,数码变焦</li>
<li>支持蓝牙2.1</li>
<li>支持动态桌面的设计</li>
</ul>
<p>###Android 2.2 Froyo</p>
<blockquote>
<p>2010年5月20日，2.2（Froyo 冻酸奶）版本软件开发工具包发布，该版本基于Linux 2.6.32内核。主要的更新如下：</p>
</blockquote>
<ul>
<li>支持将软件安装至扩展内存</li>
<li>集成Adobe Flash 10.1支持</li>
<li>新增软件启动”快速”至电话和浏览器</li>
<li>USB分享器和WiFi热点功能</li>
<li>更新Market中的批量和自动更新</li>
<li>增加对Microsoft Exchange的支持（安全政策，auto-discovery，GAL look-up）</li>
<li>集成Chrome的V8 JavaScript引擎到浏览器</li>
<li>更多软件能透过Market更新，类似2.0/2.1中的Map更新</li>
</ul>
<blockquote>
<p>注：部分标称为2.2的固件仍然在使用2.6.29的核心。这种固件可以实现大部分2.2的功能（比如Flash），但性能上与Google官方发布的2.6.32内核有一定性能差距。</p>
</blockquote>
<p>###Android 2.3 Gingerbread</p>
<blockquote>
<p>2010年12月6日，2.3（Gingerbread 姜饼）版本软件开发工具包发布，该版本基于Linux 2.6.35内核。主要更新如下：</p>
</blockquote>
<ul>
<li>修补UI,支持更大的屏幕尺寸和分辨率（WXGA及更高）</li>
<li>系统级复制粘贴</li>
<li>重新设计的多点触摸屏幕键盘</li>
<li>原生支持多个镜头（用于视频通话等）和更多传感器（陀螺仪、气压计等）</li>
<li>电话簿集成Internet Call功能</li>
<li>支持近场通信（NFC）</li>
<li>强化电源、应用程序管理功能</li>
<li>新增下载管理员</li>
<li>优化游戏开发支持</li>
<li>从YAFFS转换到ext4文件系统</li>
<li>开放了屏幕截图功能</li>
</ul>
<blockquote>
<p>2010年12月及2011年1月分别发放2.3.1和2.3.2更新包，用于改进及修复Nexus S的Bug。</p>
</blockquote>
<p>###Android 2.3.4<br>Android 2.3.4更新包增加了在Google Talk中使用语音通话和视频聊天的支持。<br>屏幕截图功能（电源键+Home）在2.3.4 才有实现出来（2011 Xperia: 长按Power键，再点击“截图”）</p>
<p>###Android 2.3.5<br>Android 2.3.5更新包于2011年7月25日正式发布，该更新包改进了个别机型的功能，针对上一个版本进行如下改进：</p>
<ul>
<li>提升了Nexus S 4G的性能，包括其他性能的提升。</li>
<li>修复了存在于三星Galaxy S中存在的蓝牙Bug。</li>
<li>升级了内置的Gmail应用程序</li>
<li>增强了滚动列表时产生的阴影动画</li>
<li>增强了内置的相机功能</li>
<li>改善了电池耗电量，增加续航时间。</li>
</ul>
<p>###Android 3.0 Honeycomb<br>Android 3.0（蜂巢 Honeycomb）软件开发包正式发布，该版本基于基于Linux 2.6.36内核，是第一个Android平板操作系统。全球第一个使用该版本操作系统的设备是摩托罗拉公司于2011年2月24日发布的Motorola Xoom平板电脑。主要更新如下：</p>
<ul>
<li>仅供平板电脑使用</li>
<li>Google eBooks上提供数百万本书</li>
<li>支持平板电脑大萤幕、高分辨率</li>
<li>新版Gmail</li>
<li>Google Talk视讯功能</li>
<li>3D加速处理</li>
<li>网页版Market（Web store）详细分类显示，依个人Android分别设定安装应用程序。</li>
<li>新的短消息通知功能</li>
<li>专为平板电脑设计的用户界面（重新设计的通知列与系统列）</li>
<li>加强多任务处理的界面</li>
<li>重新设计适用大屏幕的键盘及复制粘贴功能</li>
<li>多个标签的浏览器以及私密浏览模式</li>
<li>快速切换各种功能的相机</li>
<li>增强的图库与快速滚动的联系人界面</li>
<li>支持多核心处理器</li>
</ul>
<blockquote>
<p>3.2版优化了7寸平板显示<br>###Android 3.1<br>Android 3.1软件开发包于2011年5月10日正式发布。主要更新如下：<br>用户界面的改进</p>
</blockquote>
<ul>
<li>连接USB配件</li>
<li>扩大最近的应用程序列表</li>
<li>可调整大小的主屏幕小部件</li>
<li>支持外部键盘和鼠标等设备</li>
<li>支持操纵杆和游戏控制器</li>
<li>FLAC音频播放支持</li>
<li>高性能的WiFi锁，维护高性能WiFi连接设备屏幕关闭时。</li>
<li>支持HTTP代理为每个连接的WiFi接入点</li>
</ul>
<p>###Android 3.2</p>
<blockquote>
<p>Android 3.2软件开发包于2011年7月15日正式发布。全球第一台使用该版本操作系统的设备是中国华为公司制造生产的MediaPad平板电脑。主要更新如下：</p>
</blockquote>
<ul>
<li>改进的硬件支持，包括为更广泛的芯片，并且进行优化。</li>
<li>增强应用程序访问SD卡上文件的能力，提供同步功能。</li>
<li>增加应用程序兼容性功能，用户可以通过使用兼容性功能适配更多应用程序。</li>
<li>新的显示支持功能，为开发人员提供更多的显示外观在不同的Android设备的控制。</li>
</ul>
<p>###Android 4.0 Ice Cream Sandwich　　</p>
<blockquote>
<p>Android 4.0（Ice Cream Sandwich 雪糕三明治）于2011年4月在<br>Google I/O大会上首次被宣布，并且于2011年10月19日正式发布Android 4.0“雪糕三明治”操作系统和搭载Android 4.0的Galaxy Nexus智能手机。 Android 4.0.1的软件开发包于2011年10月19日正式发布。Google公司的发言人加布·科恩（Gabe Cohen）指出，Android 4.0“理论上”与任何一个当前市面上搭载了Android 2.3.x 版本的设备兼容。源代码已于2011年11月14日正式公布。</p>
</blockquote>
<ul>
<li>统一了手机和平板电脑使用的系统，应用会自动根据设备选择最佳显示方式。</li>
<li>支持在系统中使用虚拟按键，该功能可以取代物理按键。改进虚拟键盘可以产生的误操作。</li>
<li>增加截图功能（可以同时按住电源键和音量向下键进行截图操作）。</li>
<li>在锁屏状态下也可以对用户设置的某些应用程序进行操作</li>
<li>脸部识别进行锁屏，可以通过脸部识别进行锁屏。</li>
<li>新标签页模式的网页浏览器，支持最大同时打开16个标签页。</li>
<li>自动同步用户手机中的网页书签，可以在桌面版Chrome和其他Android设备中进行同步</li>
<li>内置流量监控功能。</li>
<li>与其他第三方应用程序进行无缝衔接，用户可以在任何界面看到自己需要的消息和图像。</li>
<li>Google Search Bar会设置在最上方</li>
<li>Apps/Widgets会类似Honeycomb模样</li>
<li>增加支持硬件加速的功能</li>
<li>Wi-Fi直连功能</li>
<li>支持1080p视频播放和录制</li>
</ul>
<p>###Android 4.1/4.2/4.3 Jelly Bean</p>
<blockquote>
<p>Android 4.1（Jelly Bean“果冻豆”）更新包于2012年6月28日在Google I/O大会上随搭载Android 4.1的Nexus 7平板电脑一起发布。</p>
</blockquote>
<ul>
<li>大幅改变用户界面设计</li>
<li>更多的Google云集成</li>
<li>恶意软件的保护措施，强化ASLR</li>
<li>Google Play 采用智能升级，更新应用只会下载有改变的部分以节约时间、流量、电量，平均只需下载原APK文件的三分之一。</li>
<li>不会内置Flash Player，并且Adobe声明停止开发，但可自行安装APK。</li>
</ul>
<p>###Android 4.2</p>
<blockquote>
<p>Google原本预计于2012年10月29日于纽约发布Android 4.2，但因为飓风桑迪吹袭被取消，而改以新闻稿发布，以“一种新口味的果冻豆”（A new flavor of Jelly Bean）作口号。首款搭载Android 4.2的手机LG Nexus 4及平板电脑Nexus 10于2012年11月23日上市。</p>
</blockquote>
<ul>
<li>PhotoSphere 360°全景拍摄</li>
<li>手势输入键盘</li>
<li>改进锁屏：支持Widget，可于屏幕锁定界面直接打开相机功能。</li>
<li>Daydream屏幕保护程序功能</li>
<li>可直接进行操作的状态通知列功能</li>
<li>支持多重账户（仅适用于平板电脑）</li>
<li>Miracast无线显示分享功能</li>
<li>连点三次可放大整个显示页及两指旋转和缩放</li>
<li>增加为盲人用户设计的语音输出及手势模式导航功能</li>
<li>内置时钟新增世界时钟，秒表和定时器</li>
</ul>
<p>###Android 4.3</p>
<blockquote>
<p>2013年7月24日与Nexus 7平板二代同步发表，主要更新如下：</p>
</blockquote>
<ul>
<li>支持多用户登录，支持一台终端设备上有多个登录帐号。</li>
<li>“蓝牙低功耗”功能，开启蓝牙后，耗电量相比之前大幅降低。 支持更多缓冲器对象</li>
<li>新版OpenGL ES 3.0着色语言，支持32 位整数和浮点数据类型以及操作。</li>
<li>多重渲染目标（Multiple Render Targets），让GPU一次性渲染多个纹理。</li>
<li>多重采样抗锯齿（MSAA Render To Texture），让3D物体的边缘不出现毛刺，可提升图像效果。</li>
<li>使用统一的纹理压缩格式ETC</li>
<li>增加TRIM指令，使得内置存储（Internal Storage）不会越用越慢。</li>
<li>新增App Opt功能（默认隐藏），允许用户强行解除已安装应用的特定权限。</li>
</ul>
<p>###Android 4.4 KitKat</p>
<blockquote>
<p>2013年9月3日，Google在Android.com上宣布下一版本命名为KitKat“奇巧”。版本号为4.4。原始开发代号为Key Lime Pie“酸柠派”。此外，Google在此版本封锁了Flash Player，用户由Android 4.3升级到Android 4.4会变得无法播放Flash。虽然Adobe早在2012年宣布停止支持Flash Player，Android 4.0是最后一个支持版本。但用户只要到官方网站下载APK，亦能在Android 4.1到Android 4.3上播放Flash。现在已有XDA论坛的开发者成功破解了Android 4.4 KitKat，但只能在Dolphin Browser上看到Flash。</p>
</blockquote>
<ul>
<li>支持语音打开Google Now (在主画面说出“OK Google”)</li>
<li>在阅读电子书、玩游戏、看电影时支持全屏模式（Immersive Mode）</li>
<li>优化存储器使用，在多任务处理时有更佳工作的表现。</li>
<li>旧有的SMS应用程序集成至新版本的Hangouts应用程序</li>
<li>支持Google Cloud Print服务，让用户可以利用户中或办公室中连接至Cloud Print的打印机，印出文件。</li>
<li>全新的原生计步器</li>
<li>全新的NFC付费集成</li>
<li>全新的非Java虚拟机运行环境ART（Android Runtime）</li>
<li>支持Message Access Profile（MAP）</li>
<li>支持Chromecast及新的Chrome功能</li>
<li>支持隐闭字幕</li>
</ul>
<p>###Android 5.0 Lollipop</p>
<blockquote>
<p>开发代号：Android L<br>2014年6月25日于Google I/O 2014大会上发布Developer版（Android L），之后在2014年10月15日正式发布且名称定为Lollipop“棒棒糖”。</p>
</blockquote>
<ul>
<li>采用全新Material Design界面</li>
<li>支持64位处理器</li>
<li>全面由Dalvik转用ART(Android Runtime)编译，性能可提升四倍</li>
<li>预载省电及充电预测功能</li>
<li>新增自动内容加密功能</li>
<li>新增多人设备分享功能，可在其他设备登录自己账号，并获取用户的联系人、日历等Google云数据</li>
<li>强化网络及传输连接性，包括Wi-Fi、蓝牙及NFC</li>
<li>强化多媒体功能，例如支持RAW格式拍摄</li>
<li>提供低视力的设置，以协助色弱人士</li>
</ul>
<p>###Android 6.0 Marshmallow</p>
<blockquote>
<p>Android的6.0版本，即盛传已久的Android M已经在Google 2015年的 I/O大会上被正式发布。一个在业内已经被热议的议题是：Android M“为工作升级而生”（Android for Work Update）。有业内人士解释道：“Android M将把Android的强大功能拓展至任何你所能看到的工作领域。”<br>Google I/O 2015大会如约已于2015年5月28日举行。在发布会上代号为“Marshmallow（棉花糖）”的安卓6.0系统正式推出。</p>
</blockquote>
<ul>
<li>应用权限管理</li>
<li>SD卡可能和内置存储“合并”</li>
<li>Android Pay</li>
<li> 原生指纹识别认证</li>
<li>自动应用数据备份</li>
<li>App Links（尽量减少诸如“你想要使用什么来打开这个？”的提醒）</li>
<li>可视化的语音邮件支持</li>
<li>在设置中新出现的全新“Memory”选项条目（早期版本出现，不过后来被隐藏）</li>
<li> 在完成截图之后可以通过通知中心直接删除截图</li>
<li>Google Now Launcher支持横屏模式</li>
<li>带滚动条和垂直滚动条支持的全新应用和窗口小部件抽屉</li>
<li> 支持原生点击唤醒功能</li>
<li> 原生4K输出支持</li>
<li> 严格的APK安装文件验证</li>
<li> 支持MIDI</li>
<li>USB Type-C端口支持</li>
<li>全新的启动动画</li>
<li>引入“语音交互”API在应用中提供更好的语音支持</li>
<li> 可通过语音命令切换到省电模式</li>
<li>可以通过蓝牙键盘快捷方式来撤销和重做文本</li>
<li> 在联系人应用中能够对已经添加的联系人进行合并、删除或者分享功能。</li>
<li>会有针对文本选择的浮动工具栏出现，以便于更快的选择文本</li>
<li>分屏键盘</li>
<li>原生Flashlight API</li>
</ul>
<p>###Android 7.0 N</p>
<blockquote>
<p>Android 7.0是谷歌推出的智能手机操作系统，代号为：Android N。谷歌2016年的I/O开发者大会在美西时间2016年5月18-20日召开，地点为山景城的Shoreline Ampitheatre圆形剧场，新版的Android N系统正式发布。<br>谷歌在2016年3月10日凌晨正式放出了Android 7.0的首个测试版本Developer Preview，数据包大小在1.1GB左右。谷歌官方已放出安装包镜像，支持Nexus 6P、Nexus 5X、Nexus 6、Pixel C、Nexus 9以及Nexus Player这几款设备。功能方面，Android 7.0新功能以实用为主，比如分屏多任务、全新设计的通知控制栏等等。<br>Android7.0系统的初次公开亮相于2016年5月18日的GoogleI/O大会。<br>新功能[6]  ：<br>有分析预测，2016年到来的Android系统也将会拥有iPhone6s的3DTouch功能。谷歌将会学习iPhone6s上的3DTouch功能，为Android用户提供相似的移动体验。<br>AndroidN会加入3DTouch功能，这和谷歌的应用设计和功能政策有关。使用谷歌产品和服务的人都十分清楚，谷歌想要提供统一的用户体验，无论他们使用的是哪一种“计算机”——手机、平板电脑、PC、iOS、Android、Mac、Windows还是Chrome，谷歌都希望能为全部的用户提供一致性的体验。<br>谷歌在旗下的各个操作系统中使用了MaterialDesign设计元素，也在不同平台给用户提供大致一样的功能，只是会有点小差异。<br>●分屏多任务<br>进入后台多任务管理页面，然后按住其中一个卡片，然后向上拖动至顶部即可开启分屏多任务，支持上下分栏和左右分栏，允许拖动中间的分割线调整两个APP所占的比例。目前，安卓7.0开发者预览版支持全部第三方应用尝试分屏操作，但个别应用适配可能存在问题，分屏后可能导致界面显示不全等问题。<br>●全新下拉快捷开关页<br>在安卓7.0中，下拉打开通知栏顶部即可显示5个用户常用的快捷开关，支持单击开关以及长按进入对应设置。如果继续下拉通知栏即可显示全部快捷开关，此外在快捷开关页右下角也会显示一个“编辑”按钮，点击之后即可自定义添加/删除快捷开关，或拖动进行排序。<br>●通知消息快捷回复<br>安卓7.0加入了全新的API，支持第三方应用通知的快捷操作和回复，例如来电会以横幅方式在屏幕顶部出现，提供接听/挂断两个按钮；信息/社交类应用通知，还可以直接打开键盘，在输入栏里进行快捷回复。<br>●通知消息归拢<br>安卓7.0会将同一应用的多条通知提示消息归拢为一项，点击该项即可展开此前的全部通知，允许用户对每个通知执行单独操作。<br>●夜间模式<br>安卓7.0中重新加入了夜间深色主题模式，该功能依然需要在系统调谐器中开启，从顶部下划打开快捷设置页，然后长按其中的设置图标，齿轮旋转10秒钟左右即可提示已开启系统调谐器，之后用户在设置中即可找到“系统调谐器”设置项。点开其中的“色彩和外观”，即可找到夜间模式，开启后即可使用全局的深色主题模式，同时亮度和色彩也会进行一定的调整，该功能可以基于时间或地理位置自动开启。另外，系统调谐器中也提供了RGB红绿蓝三色调节滑动条，允许用户手动精细调节，例如减少蓝色或增加红色以提供类似护眼模式的效果。<br>●流量保护模式<br>安卓7.0新增的流量保护模式不仅可以禁止应用在后台使用流量，还会进一步减少该应用在前台时的流量使用。其具体实现原理目前尚不清楚，推测其有可能使用了类似Chrome浏览器的数据压缩技术。此外，谷歌还扩展了ConnectivityManager API的能力，使得应用可以检测系统是否开启了流量保护模式，或者检测自己是否在白名单中。安卓7.0允许用户单独针对每个应用，选择是否开启数据保护模式。<br>●全新设置样式<br>安卓7.0启用了全新的设置样式，首先每个分类下各个子项之间的分割线消失了，只保留分类之间的分割线。全新的设置菜单还提供了一个绿色的顶栏，允许用户通过后方的下拉箭头，快速设定勿扰模式等。除了勿扰模式外，顶栏菜单还可以显示诸多其他的设置状态，例如数据流量的使用情况，自动亮度是否开启等。谷歌也在安卓7.0的设置中加入了汉堡菜单，在二级设置界面中的左上角，你就会看到这个汉堡菜单，点击后即可看到所有设置项，方便用户快速跳转。<br>●改进的Doze休眠机制<br>谷歌在安卓7.0中对Doze休眠机制做了进一步的优化，在此前的安卓6.0中，Doze深度休眠机制对于改善安卓的续航提供了巨大的作用。而在安卓7.0中，谷歌对Doze进行了更多的优化，休眠机制的使用规则和场景有所扩展，例如只要手动在后台删掉应用卡片，关屏后该应用就会被很快深度休眠。<br>●系统级电话黑名单功能<br>安卓7.0将电话拦截功能变成了一个系统级功能。其它应用可以调用这个拦截名单，但只有个别应用可以写入，包括拨号应用、默认的短信应用等。被拦截号码将不会出现在来电记录中，也不会出现通知。另外用户也可以通过账户体系备份和恢复这个拦截名单，以便快速导入其它设备或账号。<br>●菜单键快速应用切换<br>双击菜单键，就能自动切换到上一个应用。此外，如果你不停地点击菜单键的话，就会在所有应用中不间断地轮换，应用窗口会自动放大，顶部还会出现倒计时条，停止点击且倒计时结束后，当前应用会自动放大并返回到前台。</p>
</blockquote>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://vchao.top/2021/08/25/hello-world/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="vchao">
      <meta itemprop="description" content="怀揣好奇，梦想改变世界的菜鸟极客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="乘风破浪">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/08/25/hello-world/" class="post-title-link" itemprop="url">Hello World</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-08-25 21:37:14" itemprop="dateCreated datePublished" datetime="2021-08-25T21:37:14+08:00">2021-08-25</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>Welcome to <a target="_blank" rel="noopener" href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a target="_blank" rel="noopener" href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a target="_blank" rel="noopener" href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a target="_blank" rel="noopener" href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p>
<h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">&quot;My New Post&quot;</span></span><br></pre></td></tr></table></figure>

<p>More info: <a target="_blank" rel="noopener" href="https://hexo.io/docs/writing.html">Writing</a></p>
<h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure>

<p>More info: <a target="_blank" rel="noopener" href="https://hexo.io/docs/server.html">Server</a></p>
<h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure>

<p>More info: <a target="_blank" rel="noopener" href="https://hexo.io/docs/generating.html">Generating</a></p>
<h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure>

<p>More info: <a target="_blank" rel="noopener" href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://vchao.top/2018/07/13/%E8%A7%86%E9%A2%91%E6%92%AD%E6%94%BE%E5%BA%93Vitamio%E7%9A%84%E4%BD%BF%E7%94%A8%E4%BB%A5%E5%8F%8A%E5%8A%9F%E8%83%BD%E6%89%A9%E5%B1%95/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="vchao">
      <meta itemprop="description" content="怀揣好奇，梦想改变世界的菜鸟极客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="乘风破浪">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2018/07/13/%E8%A7%86%E9%A2%91%E6%92%AD%E6%94%BE%E5%BA%93Vitamio%E7%9A%84%E4%BD%BF%E7%94%A8%E4%BB%A5%E5%8F%8A%E5%8A%9F%E8%83%BD%E6%89%A9%E5%B1%95/" class="post-title-link" itemprop="url">视频播放库Vitamio的使用以及功能扩展</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2018-07-13 20:46:25" itemprop="dateCreated datePublished" datetime="2018-07-13T20:46:25+08:00">2018-07-13</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-08-25 22:37:20" itemprop="dateModified" datetime="2021-08-25T22:37:20+08:00">2021-08-25</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>﻿# 概览</p>
<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>Vitamio 能够流畅播放720P甚至1080P高清MKV，FLV，MP4，MOV，TS，RMVB等常见格式的视频，还可以在 Android 与 iOS 上跨平台支持 MMS, RTSP, RTMP, HLS(m3u8) 等常见的多种视频流媒体协议，包括点播与直播。<br>Vitamio 凭借其简洁易用的 API 接口赢得了全球众多开发者的青睐，到目前，全球已经有超过 10,000 种应用在使用 Vitamio，覆盖用户超过5亿。</p>
<blockquote>
<p>最近更新较少，上一次更新（2017-04-01）已经是两年前了，但是这并不妨碍它是一个优秀的框架。</p>
</blockquote>
<p>Vitamio 官网：<a target="_blank" rel="noopener" href="http://www.vitamio.org/">http://www.vitamio.org</a><br>github: <a target="_blank" rel="noopener" href="https://github.com/yixia/VitamioBundle">https://github.com/yixia/VitamioBundle</a><br>使用博客：农民伯伯：<a target="_blank" rel="noopener" href="http://www.cnblogs.com/over140/category/409230.html%EF%BC%88%E5%BC%80%E5%8F%91%E8%80%85%E4%B9%8B%E4%B8%80%EF%BC%8C%E6%9C%89%E5%A4%A7%E9%87%8F%E7%9A%84%E6%96%87%E6%A1%A3%EF%BC%89">http://www.cnblogs.com/over140/category/409230.html（开发者之一，有大量的文档）</a></p>
<h2 id="本文内容"><a href="#本文内容" class="headerlink" title="本文内容"></a>本文内容</h2><p>本文对其使用进行了一些扩展和功能的丰富，将其整理后汇总。除集成外，扩展功能如下：</p>
<ol>
<li>双击暂停，开始播放</li>
<li>全屏播放</li>
<li>倍速播放</li>
<li>左边上下滑动调节亮度</li>
<li>右边上下滑动调节声音</li>
<li>左右滑动快进快退</li>
<li>退出时保留播放进度</li>
<li>全屏播放时根据手机方向变化，屏幕自动旋转</li>
<li>进度条控件大小和位置的设置</li>
</ol>
<h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><p><strong>个人使用免费，商用需要授权</strong><br> 大家如果商用的话，别忘了去要授权……</p>
<h1 id="集成"><a href="#集成" class="headerlink" title="集成"></a>集成</h1><h2 id="导入"><a href="#导入" class="headerlink" title="导入"></a>导入</h2><p>github地址: <a target="_blank" rel="noopener" href="https://github.com/yixia/VitamioBundle">https://github.com/yixia/VitamioBundle</a><br>首先从github上下载源文件，然后以 module的方式导入工程中，即可开始使用。</p>
<ol>
<li>导入module，在Android Studio 中依次点击 File –&gt;New –&gt; Import Module…，然后在弹出框中选择文件的路径。</li>
<li>添加依赖，打开Project Structure选项卡，点击左上角的’+’按钮，然后按照提示添加即可。 <blockquote>
<p>目前为止，github上的代码已经很久没有维护了，上次维护应该还是 [2014-04-18] 发布的 4.2.2 版本。所以并不推荐用在公司项目中，一是很久没有维护了，二是需要授权。</p>
</blockquote>
</li>
<li>打开app/src/main目录下的AndroidManifest.xml,注册io.vov.vitamio.activity.InitActivity<br><activity
 android:name="io.vov.vitamio.activity.InitActivity"
 android:configChanges="orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
 android:launchMode="singleTop"
 android:theme="@android:style/Theme.NoTitleBar"
 android:windowSoftInputMode="stateAlwaysHidden" /><br>注意:这个InitActivity存在于vitamio/src/对应的目录下,不需要用户编写.</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;activity</span><br><span class="line">    android:name=&quot;io.vov.vitamio.activity.InitActivity&quot;</span><br><span class="line">    android:configChanges=&quot;orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation&quot;</span><br><span class="line">    android:launchMode=&quot;singleTop&quot;</span><br><span class="line">    android:theme=&quot;@android:style/Theme.NoTitleBar&quot;</span><br><span class="line">    android:windowSoftInputMode=&quot;stateAlwaysHidden&quot; /&gt;</span><br></pre></td></tr></table></figure>

<p>至此,vitamio导入完毕.</p>
<h1 id="扩展功能"><a href="#扩展功能" class="headerlink" title="扩展功能"></a>扩展功能</h1><p>需求。左侧上下滑动调节亮度，右侧上下滑动调节声音，中间添加提示：<br>界面文件，因为点击之后控制器会布满屏幕，所及监听和显示组件都要添加到 MediaController中<br>在这里我们采用手势去处理</p>
<h2 id="1-双击暂停，开始播放"><a href="#1-双击暂停，开始播放" class="headerlink" title="1. 双击暂停，开始播放"></a>1. 双击暂停，开始播放</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//播放与暂停</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">playOrPause</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (videoView != <span class="keyword">null</span>)</span><br><span class="line">        <span class="keyword">if</span> (videoView.isPlaying()) &#123;</span><br><span class="line">            videoView.pause();</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            videoView.start();</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="2-全屏播放"><a href="#2-全屏播放" class="headerlink" title="2. 全屏播放"></a>2. 全屏播放</h2><p>全屏播放，点击按钮后隐藏其他控件，重设尺寸即可<br>半屏播放同理</p>
<h2 id="3-倍速播放"><a href="#3-倍速播放" class="headerlink" title="3. 倍速播放"></a>3. 倍速播放</h2><p>Vitamio 支持倍速播放，可以根据项目需求进行设置</p>
<h2 id="4-左边上下滑动调节亮度"><a href="#4-左边上下滑动调节亮度" class="headerlink" title="4. 左边上下滑动调节亮度"></a>4. 左边上下滑动调节亮度</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 滑动改变亮度</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> percent</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">onBrightnessSlide</span><span class="params">(<span class="keyword">float</span> percent)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (mBrightness &lt; <span class="number">0</span>) &#123;</span><br><span class="line">        mBrightness = activity.getWindow().getAttributes().screenBrightness;</span><br><span class="line">        <span class="keyword">if</span> (mBrightness &lt;= <span class="number">0.00f</span>)</span><br><span class="line">            mBrightness = <span class="number">0.50f</span>;</span><br><span class="line">        <span class="keyword">if</span> (mBrightness &lt; <span class="number">0.01f</span>)</span><br><span class="line">            mBrightness = <span class="number">0.01f</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 显示</span></span><br><span class="line">        <span class="comment">//mOperationBg.setImageResource(R.drawable.video_brightness_bg);</span></span><br><span class="line">        mVolumeBrightnessLayout.setVisibility(View.VISIBLE);</span><br><span class="line">        mOperationTv.setVisibility(VISIBLE);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h2 id="5-右边上下滑动调节声音"><a href="#5-右边上下滑动调节声音" class="headerlink" title="5. 右边上下滑动调节声音"></a>5. 右边上下滑动调节声音</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 滑动改变声音大小</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> percent</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">onVolumeSlide</span><span class="params">(<span class="keyword">float</span> percent)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (mVolume == -<span class="number">1</span>) &#123;</span><br><span class="line">        mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);</span><br><span class="line">        <span class="keyword">if</span> (mVolume &lt; <span class="number">0</span>)</span><br><span class="line">            mVolume = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 显示</span></span><br><span class="line">        mVolumeBrightnessLayout.setVisibility(View.VISIBLE);</span><br><span class="line">        mOperationTv.setVisibility(VISIBLE);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> index = (<span class="keyword">int</span>) (percent * mMaxVolume) + mVolume;</span><br><span class="line">    <span class="keyword">if</span> (index &gt; mMaxVolume)</span><br><span class="line">        index = mMaxVolume;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (index &lt; <span class="number">0</span>)</span><br><span class="line">        index = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">if</span> (index &gt;= <span class="number">10</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.volmn_100);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (index &gt;= <span class="number">5</span> &amp;&amp; index &lt; <span class="number">10</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.volmn_60);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (index &gt; <span class="number">0</span> &amp;&amp; index &lt; <span class="number">5</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.volmn_30);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.volmn_no);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//DecimalFormat    df   = new DecimalFormat(&quot;######0.00&quot;);</span></span><br><span class="line">    mOperationTv.setText((<span class="keyword">int</span>) (((<span class="keyword">double</span>) index / mMaxVolume)*<span class="number">100</span>)+<span class="string">&quot;%&quot;</span>);</span><br><span class="line">    <span class="comment">// 变更声音</span></span><br><span class="line">    mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="6-左右滑动快进快退"><a href="#6-左右滑动快进快退" class="headerlink" title="6. 左右滑动快进快退"></a>6. 左右滑动快进快退</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//滑动监听</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onScroll</span><span class="params">(MotionEvent e1, MotionEvent e2, <span class="keyword">float</span> distanceX, <span class="keyword">float</span> distanceY)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">float</span> mOldX = e1.getX(), mOldY = e1.getY();</span><br><span class="line">        <span class="keyword">int</span> y = (<span class="keyword">int</span>) e2.getRawY();</span><br><span class="line">        <span class="keyword">int</span> x = (<span class="keyword">int</span>) e2.getRawX();</span><br><span class="line">        Display disp = activity.getWindowManager().getDefaultDisplay();</span><br><span class="line">        <span class="keyword">int</span> windowWidth = disp.getWidth();</span><br><span class="line">        <span class="keyword">int</span> windowHeight = disp.getHeight();</span><br><span class="line">        <span class="keyword">if</span> (mOldX &gt; windowWidth * <span class="number">3.0</span> / <span class="number">4.0</span>) &#123;<span class="comment">// 右边滑动 屏幕 3/4</span></span><br><span class="line">            onVolumeSlide((mOldY - y) / windowHeight);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (mOldX &lt; windowWidth * <span class="number">1.0</span> / <span class="number">4.0</span>) &#123;<span class="comment">// 左边滑动 屏幕 1/4</span></span><br><span class="line">            onBrightnessSlide((mOldY - y) / windowHeight);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">super</span>.onScroll(e1, e2, distanceX, distanceY);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h2 id="7-退出时保留播放进度"><a href="#7-退出时保留播放进度" class="headerlink" title="7. 退出时保留播放进度"></a>7. 退出时保留播放进度</h2><p>当页面失去焦点时，保存当前播放进度数值，然后当恢复播放的时候，重新设置进度</p>
<h2 id="8-全屏播放时根据手机方向变化，屏幕自动旋转"><a href="#8-全屏播放时根据手机方向变化，屏幕自动旋转" class="headerlink" title="8. 全屏播放时根据手机方向变化，屏幕自动旋转"></a>8. 全屏播放时根据手机方向变化，屏幕自动旋转</h2><p>首先确定开始收集转屏，然后页面设置中设置为响应屏幕方向的变化，即可自动切换</p>
<h2 id="9-进度条控件大小和位置的设置"><a href="#9-进度条控件大小和位置的设置" class="headerlink" title="9. 进度条控件大小和位置的设置"></a>9. 进度条控件大小和位置的设置</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">protected</span> View <span class="title">makeControllerView</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    View v = ((LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(getResources().getIdentifier(<span class="string">&quot;mymediacontroller&quot;</span>, <span class="string">&quot;layout&quot;</span>, getContext().getPackageName()), <span class="keyword">this</span>);</span><br><span class="line">    v.setMinimumHeight(controllerWidth);</span><br><span class="line">	</span><br><span class="line">	... <span class="comment">// 省略其他代码</span></span><br><span class="line"></span><br><span class="line">    mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);</span><br><span class="line">    mMaxVolume = mAudioManager</span><br><span class="line">            .getStreamMaxVolume(AudioManager.STREAM_MUSIC);</span><br><span class="line">    <span class="keyword">return</span> v;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="完整代码"><a href="#完整代码" class="headerlink" title="完整代码"></a>完整代码</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyMediaController</span> <span class="keyword">extends</span> <span class="title">MediaController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> HIDEFRAM = <span class="number">0</span>;<span class="comment">//控制提示窗口的显示</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> SHOW_PROGRESS = <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> GestureDetector mGestureDetector;<span class="comment">//手势监听类</span></span><br><span class="line"><span class="keyword">private</span> ImageButton img_back;<span class="comment">//返回键</span></span><br><span class="line"><span class="keyword">private</span> ImageView img_Battery;<span class="comment">//电池电量显示</span></span><br><span class="line"><span class="keyword">private</span> TextView textViewTime;<span class="comment">//时间提示</span></span><br><span class="line"><span class="keyword">private</span> TextView textViewBattery;<span class="comment">//文字显示电池</span></span><br><span class="line"><span class="keyword">private</span> VideoView videoView;</span><br><span class="line"><span class="keyword">private</span> Activity activity;</span><br><span class="line"><span class="keyword">private</span> Context context;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> controllerWidth = <span class="number">0</span>;<span class="comment">//设置mediaController高度为了使横屏时top显示在屏幕顶端</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> View mVolumeBrightnessLayout;<span class="comment">//提示窗口</span></span><br><span class="line"><span class="keyword">private</span> ImageView mOperationBg;<span class="comment">//提示图片</span></span><br><span class="line"><span class="keyword">private</span> TextView mOperationTv;<span class="comment">//提示文字</span></span><br><span class="line"><span class="keyword">private</span> AudioManager mAudioManager;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> SeekBar progress;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">boolean</span> mDragging;</span><br><span class="line"><span class="keyword">private</span> MediaPlayerControl player;</span><br><span class="line"><span class="comment">//最大声音</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> mMaxVolume;</span><br><span class="line"><span class="comment">// 当前声音</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> mVolume = -<span class="number">1</span>;</span><br><span class="line"><span class="comment">//当前亮度</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">float</span> mBrightness = -<span class="number">1f</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//返回监听</span></span><br><span class="line"><span class="keyword">private</span> View.OnClickListener backListener = <span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(activity != <span class="keyword">null</span>)&#123;</span><br><span class="line">            activity.finish();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> Handler myHandler = <span class="keyword">new</span> Handler() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">handleMessage</span><span class="params">(Message msg)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">long</span> pos;</span><br><span class="line">        <span class="keyword">switch</span> (msg.what) &#123;</span><br><span class="line">            <span class="keyword">case</span> HIDEFRAM:<span class="comment">//隐藏提示窗口</span></span><br><span class="line">                mVolumeBrightnessLayout.setVisibility(View.GONE);</span><br><span class="line">                mOperationTv.setVisibility(View.GONE);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//videoview 用于对视频进行控制的等，activity为了退出</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">MyMediaController</span><span class="params">(Context context, VideoView videoView , Activity activity)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">super</span>(context);</span><br><span class="line">    <span class="keyword">this</span>.context = context;</span><br><span class="line">    <span class="keyword">this</span>.videoView = videoView;</span><br><span class="line">    <span class="keyword">this</span>.activity = activity;</span><br><span class="line">    WindowManager wm = (WindowManager) context</span><br><span class="line">            .getSystemService(Context.WINDOW_SERVICE);</span><br><span class="line">    controllerWidth = wm.getDefaultDisplay().getWidth();</span><br><span class="line">    mGestureDetector = <span class="keyword">new</span> GestureDetector(context, <span class="keyword">new</span> MyGestureListener());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">protected</span> View <span class="title">makeControllerView</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    View v = ((LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(getResources().getIdentifier(<span class="string">&quot;mymediacontroller&quot;</span>, <span class="string">&quot;layout&quot;</span>, getContext().getPackageName()), <span class="keyword">this</span>);</span><br><span class="line">    v.setMinimumHeight(controllerWidth);</span><br><span class="line">    <span class="comment">//TOP</span></span><br><span class="line"><span class="comment">//        img_back = (ImageButton) v.findViewById(getResources().getIdentifier(&quot;mediacontroller_top_back&quot;, &quot;id&quot;, context.getPackageName()));</span></span><br><span class="line"><span class="comment">//        img_Battery = (ImageView) v.findViewById(getResources().getIdentifier(&quot;mediacontroller_imgBattery&quot;, &quot;id&quot;, context.getPackageName()));</span></span><br><span class="line"><span class="comment">//        img_back.setOnClickListener(backListener);</span></span><br><span class="line"><span class="comment">//        textViewBattery = (TextView)v.findViewById(getResources().getIdentifier(&quot;mediacontroller_Battery&quot;, &quot;id&quot;, context.getPackageName()));</span></span><br><span class="line"><span class="comment">//        textViewTime = (TextView)v.findViewById(getResources().getIdentifier(&quot;mediacontroller_time&quot;, &quot;id&quot;, context.getPackageName()));</span></span><br><span class="line">    img_back = (ImageButton) v.findViewById(R.id.mediacontroller_top_back);</span><br><span class="line">    img_Battery = (ImageView) v.findViewById(R.id.mediacontroller_imgBattery);</span><br><span class="line">    img_back.setOnClickListener(backListener);</span><br><span class="line">    textViewBattery = (TextView)v.findViewById(R.id.mediacontroller_Battery);</span><br><span class="line">    textViewTime = (TextView)v.findViewById(R.id.mediacontroller_time);</span><br><span class="line">    progress = (SeekBar)v.findViewById(R.id.mediacontroller_seekbar);</span><br><span class="line">    <span class="comment">//mid</span></span><br><span class="line">    mVolumeBrightnessLayout = (RelativeLayout)v.findViewById(R.id.operation_volume_brightness);</span><br><span class="line">    mOperationBg = (ImageView)v.findViewById(R.id.operation_bg);</span><br><span class="line">    mOperationTv = (TextView) v.findViewById(R.id.operation_tv);</span><br><span class="line">    mOperationTv.setVisibility(View.GONE);</span><br><span class="line">    mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);</span><br><span class="line">    mMaxVolume = mAudioManager</span><br><span class="line">            .getStreamMaxVolume(AudioManager.STREAM_MUSIC);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> v;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">dispatchKeyEvent</span><span class="params">(KeyEvent event)</span> </span>&#123;</span><br><span class="line">    System.out.println(<span class="string">&quot;MYApp-MyMediaController-dispatchKeyEvent&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onTouchEvent</span><span class="params">(MotionEvent event)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (mGestureDetector.onTouchEvent(event)) <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    <span class="comment">// 处理手势结束</span></span><br><span class="line">    <span class="keyword">switch</span> (event.getAction() &amp; MotionEvent.ACTION_MASK) &#123;</span><br><span class="line">        <span class="keyword">case</span> MotionEvent.ACTION_UP:</span><br><span class="line">            endGesture();</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">super</span>.onTouchEvent(event);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 手势结束</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">endGesture</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    mVolume = -<span class="number">1</span>;</span><br><span class="line">    mBrightness = -<span class="number">1f</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 隐藏</span></span><br><span class="line">    myHandler.removeMessages(HIDEFRAM);</span><br><span class="line">    myHandler.sendEmptyMessageDelayed(HIDEFRAM, <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="class"><span class="keyword">class</span> <span class="title">MyGestureListener</span> <span class="keyword">extends</span> <span class="title">GestureDetector</span>.<span class="title">SimpleOnGestureListener</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onSingleTapUp</span><span class="params">(MotionEvent e)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onSingleTapConfirmed</span><span class="params">(MotionEvent e)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//当收拾结束，并且是单击结束时，控制器隐藏/显示</span></span><br><span class="line">        toggleMediaControlsVisiblity();</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">super</span>.onSingleTapConfirmed(e);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onDown</span><span class="params">(MotionEvent e)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="comment">//滑动监听</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onScroll</span><span class="params">(MotionEvent e1, MotionEvent e2, <span class="keyword">float</span> distanceX, <span class="keyword">float</span> distanceY)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">float</span> mOldX = e1.getX(), mOldY = e1.getY();</span><br><span class="line">        <span class="keyword">int</span> y = (<span class="keyword">int</span>) e2.getRawY();</span><br><span class="line">        <span class="keyword">int</span> x = (<span class="keyword">int</span>) e2.getRawX();</span><br><span class="line">        Display disp = activity.getWindowManager().getDefaultDisplay();</span><br><span class="line">        <span class="keyword">int</span> windowWidth = disp.getWidth();</span><br><span class="line">        <span class="keyword">int</span> windowHeight = disp.getHeight();</span><br><span class="line">        <span class="keyword">if</span> (mOldX &gt; windowWidth * <span class="number">3.0</span> / <span class="number">4.0</span>) &#123;<span class="comment">// 右边滑动 屏幕 3/4</span></span><br><span class="line">            onVolumeSlide((mOldY - y) / windowHeight);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (mOldX &lt; windowWidth * <span class="number">1.0</span> / <span class="number">4.0</span>) &#123;<span class="comment">// 左边滑动 屏幕 1/4</span></span><br><span class="line">            onBrightnessSlide((mOldY - y) / windowHeight);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">super</span>.onScroll(e1, e2, distanceX, distanceY);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//双击暂停或开始</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onDoubleTap</span><span class="params">(MotionEvent e)</span> </span>&#123;</span><br><span class="line">        playOrPause();</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onFling</span><span class="params">(MotionEvent e1, MotionEvent e2, <span class="keyword">float</span> velocityX, <span class="keyword">float</span> velocityY)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">super</span>.onFling(e1, e2, velocityX, velocityY);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 滑动改变声音大小</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> percent</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">onVolumeSlide</span><span class="params">(<span class="keyword">float</span> percent)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (mVolume == -<span class="number">1</span>) &#123;</span><br><span class="line">        mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);</span><br><span class="line">        <span class="keyword">if</span> (mVolume &lt; <span class="number">0</span>)</span><br><span class="line">            mVolume = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 显示</span></span><br><span class="line">        mVolumeBrightnessLayout.setVisibility(View.VISIBLE);</span><br><span class="line">        mOperationTv.setVisibility(VISIBLE);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> index = (<span class="keyword">int</span>) (percent * mMaxVolume) + mVolume;</span><br><span class="line">    <span class="keyword">if</span> (index &gt; mMaxVolume)</span><br><span class="line">        index = mMaxVolume;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (index &lt; <span class="number">0</span>)</span><br><span class="line">        index = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">if</span> (index &gt;= <span class="number">10</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.volmn_100);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (index &gt;= <span class="number">5</span> &amp;&amp; index &lt; <span class="number">10</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.volmn_60);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (index &gt; <span class="number">0</span> &amp;&amp; index &lt; <span class="number">5</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.volmn_30);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.volmn_no);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//DecimalFormat    df   = new DecimalFormat(&quot;######0.00&quot;);</span></span><br><span class="line">    mOperationTv.setText((<span class="keyword">int</span>) (((<span class="keyword">double</span>) index / mMaxVolume)*<span class="number">100</span>)+<span class="string">&quot;%&quot;</span>);</span><br><span class="line">    <span class="comment">// 变更声音</span></span><br><span class="line">    mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 滑动改变亮度</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> percent</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">onBrightnessSlide</span><span class="params">(<span class="keyword">float</span> percent)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (mBrightness &lt; <span class="number">0</span>) &#123;</span><br><span class="line">        mBrightness = activity.getWindow().getAttributes().screenBrightness;</span><br><span class="line">        <span class="keyword">if</span> (mBrightness &lt;= <span class="number">0.00f</span>)</span><br><span class="line">            mBrightness = <span class="number">0.50f</span>;</span><br><span class="line">        <span class="keyword">if</span> (mBrightness &lt; <span class="number">0.01f</span>)</span><br><span class="line">            mBrightness = <span class="number">0.01f</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 显示</span></span><br><span class="line">        <span class="comment">//mOperationBg.setImageResource(R.drawable.video_brightness_bg);</span></span><br><span class="line">        mVolumeBrightnessLayout.setVisibility(View.VISIBLE);</span><br><span class="line">        mOperationTv.setVisibility(VISIBLE);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    WindowManager.LayoutParams lpa = activity.getWindow().getAttributes();</span><br><span class="line">    lpa.screenBrightness = mBrightness + percent;</span><br><span class="line">    <span class="keyword">if</span> (lpa.screenBrightness &gt; <span class="number">1.0f</span>)</span><br><span class="line">        lpa.screenBrightness = <span class="number">1.0f</span>;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (lpa.screenBrightness &lt; <span class="number">0.01f</span>)</span><br><span class="line">        lpa.screenBrightness = <span class="number">0.01f</span>;</span><br><span class="line">    activity.getWindow().setAttributes(lpa);</span><br><span class="line"></span><br><span class="line">    mOperationTv.setText((<span class="keyword">int</span>) (lpa.screenBrightness * <span class="number">100</span>) + <span class="string">&quot;%&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (lpa.screenBrightness * <span class="number">100</span> &gt;= <span class="number">90</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.light_100);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (lpa.screenBrightness * <span class="number">100</span> &gt;= <span class="number">80</span> &amp;&amp; lpa.screenBrightness * <span class="number">100</span> &lt; <span class="number">90</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.light_90);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (lpa.screenBrightness * <span class="number">100</span> &gt;= <span class="number">70</span> &amp;&amp; lpa.screenBrightness * <span class="number">100</span> &lt; <span class="number">80</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.light_80);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (lpa.screenBrightness * <span class="number">100</span> &gt;= <span class="number">60</span> &amp;&amp; lpa.screenBrightness * <span class="number">100</span> &lt; <span class="number">70</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.light_70);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (lpa.screenBrightness * <span class="number">100</span> &gt;= <span class="number">50</span> &amp;&amp; lpa.screenBrightness * <span class="number">100</span> &lt; <span class="number">60</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.light_60);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (lpa.screenBrightness * <span class="number">100</span> &gt;= <span class="number">40</span> &amp;&amp; lpa.screenBrightness * <span class="number">100</span> &lt; <span class="number">50</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.light_50);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (lpa.screenBrightness * <span class="number">100</span> &gt;= <span class="number">30</span> &amp;&amp; lpa.screenBrightness * <span class="number">100</span> &lt; <span class="number">40</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.light_40);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (lpa.screenBrightness * <span class="number">100</span> &gt;= <span class="number">20</span> &amp;&amp; lpa.screenBrightness * <span class="number">100</span> &lt; <span class="number">20</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.light_30);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (lpa.screenBrightness * <span class="number">100</span> &gt;= <span class="number">10</span> &amp;&amp; lpa.screenBrightness * <span class="number">100</span> &lt; <span class="number">20</span>) &#123;</span><br><span class="line">        mOperationBg.setImageResource(R.drawable.light_20);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setTime</span><span class="params">(String time)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (textViewTime != <span class="keyword">null</span>)</span><br><span class="line">        textViewTime.setText(time);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//显示电量，</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setBattery</span><span class="params">(String stringBattery)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(textViewTime != <span class="keyword">null</span> &amp;&amp; img_Battery != <span class="keyword">null</span>)&#123;</span><br><span class="line">        textViewBattery.setText(stringBattery + <span class="string">&quot;%&quot;</span>);</span><br><span class="line">        <span class="keyword">int</span> battery = Integer.valueOf(stringBattery);</span><br><span class="line">        <span class="keyword">if</span>(battery &lt; <span class="number">15</span>)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_15));</span><br><span class="line">        <span class="keyword">if</span>(battery &lt; <span class="number">30</span> &amp;&amp; battery &gt;= <span class="number">15</span>)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_15));</span><br><span class="line">        <span class="keyword">if</span>(battery &lt; <span class="number">45</span> &amp;&amp; battery &gt;= <span class="number">30</span>)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_30));</span><br><span class="line">        <span class="keyword">if</span>(battery &lt; <span class="number">60</span> &amp;&amp; battery &gt;= <span class="number">45</span>)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_45));</span><br><span class="line">        <span class="keyword">if</span>(battery &lt; <span class="number">75</span> &amp;&amp; battery &gt;= <span class="number">60</span>)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_60));</span><br><span class="line">        <span class="keyword">if</span>(battery &lt; <span class="number">90</span> &amp;&amp; battery &gt;= <span class="number">75</span>)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_75));</span><br><span class="line">        <span class="keyword">if</span>(battery &gt; <span class="number">90</span> )img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_90));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//隐藏/显示</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">toggleMediaControlsVisiblity</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (isShowing()) &#123;</span><br><span class="line">        hide();</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        show();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//播放与暂停</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">playOrPause</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (videoView != <span class="keyword">null</span>)</span><br><span class="line">        <span class="keyword">if</span> (videoView.isPlaying()) &#123;</span><br><span class="line">            videoView.pause();</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            videoView.start();</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>




      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://vchao.top/2018/04/12/Android%20Studio%E4%B8%AD%E6%80%8E%E4%B9%88%E4%BD%BF%E7%94%A8DDMS%E5%B7%A5%E5%85%B7%EF%BC%9F/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="vchao">
      <meta itemprop="description" content="怀揣好奇，梦想改变世界的菜鸟极客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="乘风破浪">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2018/04/12/Android%20Studio%E4%B8%AD%E6%80%8E%E4%B9%88%E4%BD%BF%E7%94%A8DDMS%E5%B7%A5%E5%85%B7%EF%BC%9F/" class="post-title-link" itemprop="url">Android Studio中怎么使用DDMS工具？</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2018-04-12 17:51:40" itemprop="dateCreated datePublished" datetime="2018-04-12T17:51:40+08:00">2018-04-12</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-08-21 19:37:34" itemprop="dateModified" datetime="2021-08-21T19:37:34+08:00">2021-08-21</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>﻿&gt; 随着Android Studio的广泛使用，开发人员对相关工具的使用需求更加凸显。昨天在一个android studio教程网站上，看到一篇有关DDMS工具使用的相关知识，感觉很不错，分享给大家，一起来看看吧，新技能get走起~~</p>
<h2 id="DDMS"><a href="#DDMS" class="headerlink" title="DDMS"></a>DDMS</h2><p>首先，我们需要了解的是DDMS工具是个什么鬼？</p>
<p>其实，DDMS（Dalvik Debug Monitor Service），是 Android 开发环境中的Dalvik虚拟机调试监控服务。可以进行的操作有：为测试设备截屏，查看特定行程中正在运行的线程以及堆信息、Logcat、广播状态信息、模拟电话呼叫、接收SMS、虚拟地理坐标等，功能非常强大，对于安卓开发者来说是一个非常好的工具，下面来看看其具体用法吧。</p>
<p> Android Studio开发工具中，打开DDMS ：<br><img src="https://img-blog.csdn.net/20180413183031915?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poZW5nX3dlaWNoYW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="打开DDMS"></p>
<h2 id="详细功能："><a href="#详细功能：" class="headerlink" title="详细功能："></a>详细功能：</h2><ul>
<li>1.Devices：查看到所有与DDMS连接的模拟器详细信息，以及每个模拟器正在运行的APP进程，每个进程最右边相对应的是与调试器链接的端口。</li>
</ul>
<ul>
<li><p>2.Emulator Control：实现对模拟器的控制，如：接听电话，根据选项模拟各种不同网络情况，模拟短信发送及虚拟地址坐标用于测试GPS功能等。</p>
</li>
<li><p>3.LogCat ：查看日志输入信息，可以对日志输入进行Filter过滤一些调试的信息筛选查看等。</p>
</li>
<li><p>4.File Exporler:File Exporler文件浏览器，查看Android模拟器中的文件，可以很方便的导入/出文件。</p>
</li>
<li><p>5.Heap：查看应用中内存使用情况。</p>
</li>
<li><p>6.Dump HPROF file:点击DDMS工具条上面的Dump HPROF文件按钮，选择文件存储位置，然后在运行hprof-conv。可以用MAT分析heap dumps启 动MAT然后加载刚才我们生成的HPROF文件。MAT是一个强大的工具，讲述它所有的特性超出了本文的范围，所以我只想演示一种你可以用来检测 泄露的方法：直方图（Histogram）视图。它显示了一个可以排序的类实例的列表，内容包括：shallow heap（所有实例的内存使用总和），或者retained heap（所有类实例被分配的内存总和，里面也包括他们所有引用的对象）等。</p>
</li>
<li><p>7 . Screen captrue:截屏操作<br>当想获取到模拟器或者测试机上的截图时，没有必要手机截图，然后发到电脑上了，可以直接通过截图按钮进行截图操作，然后保存到电脑上啦~<br><img src="https://img-blog.csdn.net/20180413190727650?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poZW5nX3dlaWNoYW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt=" 截屏操作 "></p>
</li>
<li><p>8 . 查看特定页面的展示及布局元素构成：(Dump View Hierarchy for UI Automator )<br>当看见一个应用页面，想知道它的布局元素构成的时候，就可以用到这个功能了。这个功能名称叫<strong>Dump View Hierarchy for UI Automator</strong> （用于UI自动化的转储视图层次结构）。</p>
</li>
</ul>
<p> <img src="https://img-blog.csdn.net/20180413185051100?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poZW5nX3dlaWNoYW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="分析页面布局 "></p>
<p>9.Thread:查看进程中线程情况。</p>
<p>10.其它功能：<br>查看进程中的线程：<br>查看内存信息：</p>
<p>文件管理，可以对文件进行导入导出，真机很多操作可能需要Root权限才能进行。模拟器的话可以模拟发短信，打电话，定位等。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/page/2/"><i class="fa fa-angle-left" aria-label="上一页"></i></a><a class="page-number" href="/">1</a><a class="page-number" href="/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/page/4/">4</a><a class="page-number" href="/page/5/">5</a><a class="extend next" rel="next" href="/page/4/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">vchao</p>
  <div class="site-description" itemprop="description">怀揣好奇，梦想改变世界的菜鸟极客</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">46</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
        <span class="site-state-item-count">4</span>
        <span class="site-state-item-name">分类</span>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">27</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        
  <div class="beian"><a href="https://beian.miit.gov.cn/" rel="noopener" target="_blank">冀ICP备 17022751号-1 </a>
      <img src="https://beian.miit.gov.cn" style="display: inline-block;">
  </div>

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">vchao</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://muse.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/muse.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

</body>
</html>
